///////////////////////////////////////////////////////////////////////////
//
// SDL_PCService() - Handles playing the next sample in a PC sound
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_PCService(void)
{
byte s;
word t;
if (pcSound)
{
s = *pcSound++;
if (s != pcLastSample)
{
asm pushf
asm cli
pcLastSample = s;
if (s) // We have a frequency!
{
t = pcSoundLookup[s];
asm mov bx,[t]
asm mov al,0xb6 // Write to channel 2 (speaker) timer
asm out 43h,al
asm mov al,bl
asm out 42h,al // Low byte
asm mov al,bh
asm out 42h,al // High byte
asm in al,0x61 // Turn the speaker & gate on
asm or al,3
asm out 0x61,al
}
else // Time for some silence
{
asm in al,0x61 // Turn the speaker & gate off
asm and al,0xfc // ~3
asm out 0x61,al
}
asm popf
}
if (!(--pcLengthLeft))
{
SDL_PCStopSound();
SDL_SoundFinished();
}
}
}
#endif
///////////////////////////////////////////////////////////////////////////
//
// SDL_ShutPC() - Turns off the pc speaker
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_ShutPC(void)
{
asm pushf
asm cli
pcSound = 0;
asm in al,0x61 // Turn the speaker & gate off
asm and al,0xfc // ~3
asm out 0x61,al
asm popf
}
//
// Stuff for digitized sounds
//
memptr
SDL_LoadDigiSegment(word page)
{
memptr addr;
#if 0 // 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,10 // bright green
asm out dx,al
#endif
addr = PM_GetSoundPage(page);
PM_SetPageLock(PMSoundStart + page,pml_Locked);
#if 0 // 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
return(addr);
}
void
SDL_PlayDigiSegment(memptr addr,word len)
{
switch (DigiMode)
{
case sds_PC:
SDL_PCPlaySample(addr,len);
break;
case sds_SoundSource:
SDL_SSPlaySample(addr,len);
break;
case sds_SoundBlaster:
SDL_SBPlaySample(addr,len);
break;
}
}
void
SD_StopDigitized(void)
{
int i;
asm pushf
asm cli
DigiLeft = 0;
DigiNextAddr = nil;
DigiNextLen = 0;
DigiMissed = false;
DigiPlaying = false;
DigiNumber = DigiPriority = 0;
SoundPositioned = false;
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
SDL_SoundFinished();
switch (DigiMode)
{
case sds_PC:
SDL_PCStopSample();
break;
case sds_SoundSource:
SDL_SSStopSample();
break;
case sds_SoundBlaster:
SDL_SBStopSample();
break;
}
asm popf
for (i = DigiLastStart;i DigiLastEnd;i++)
PM_SetPageLock(i + PMSoundStart,pml_Unlocked);
DigiLastStart = 1;
DigiLastEnd = 0;
}
void
SD_Poll(void)
{
if (DigiLeft && !DigiNextAddr)
{
DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
DigiLeft -= DigiNextLen;
if (!DigiLeft)
DigiLastSegment = true;
DigiNextAddr = SDL_LoadDigiSegment(DigiPage++);
}
if (DigiMissed && DigiNextAddr)
{
SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
DigiNextAddr = nil;
DigiMissed = false;
if (DigiLastSegment)
{
DigiPlaying = false;
DigiLastSegment = false;
}
}
SDL_SetTimerSpeed();
}
void
SD_SetPosition(int leftpos,int rightpos)
{
if
(
(leftpos 0)
|| (leftpos > 15)
|| (rightpos 0)
|| (rightpos > 15)
|| ((leftpos == 15) && (rightpos == 15))
)
Quit("SD_SetPosition: Illegal position");
switch (DigiMode)
{
case sds_SoundBlaster:
SDL_PositionSBP(leftpos,rightpos);
break;
}
}
void
SD_PlayDigitized(word which,int leftpos,int rightpos)
{
word len;
memptr addr;
if (!DigiMode)
return;
SD_StopDigitized();
if (which >= NumDigi)
Quit("SD_PlayDigitized: bad sound number");
SD_SetPosition(leftpos,rightpos);
DigiPage = DigiList[(which * 2) + 0];
DigiLeft = DigiList[(which * 2) + 1];
DigiLastStart = DigiPage;
DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize);
len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
addr = SDL_LoadDigiSegment(DigiPage++);
DigiPlaying = true;
DigiLastSegment = false;
SDL_PlayDigiSegment(addr,len);
DigiLeft -= len;
if (!DigiLeft)
DigiLastSegment = true;
SD_Poll();
}
void
SDL_DigitizedDone(void)
{
if (DigiNextAddr)
{
SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
DigiNextAddr = nil;
DigiMissed = false;
}
else
{
if (DigiLastSegment)
{
DigiPlaying = false;
DigiLastSegment = false;
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
{
SDL_SoundFinished();
}
else
DigiNumber = DigiPriority = 0;
SoundPositioned = false;
}
else
DigiMissed = true;
}
}
void
SD_SetDigiDevice(SDSMode mode)
{
boolean devicenotpresent;
if (mode == DigiMode)
return;
SD_StopDigitized();
devicenotpresent = false;
switch (mode)
{
case sds_SoundBlaster:
if (!SoundBlasterPresent)
{
if (SoundSourcePresent)
mode = sds_SoundSource;
else
devicenotpresent = true;
}
break;
case sds_SoundSource:
if (!SoundSourcePresent)
devicenotpresent = true;
break;
}
if (!devicenotpresent)
{
if (DigiMode == sds_SoundSource)
SDL_ShutSS();
DigiMode = mode;
if (mode == sds_SoundSource)
SDL_StartSS();
SDL_SetTimerSpeed();
}
}
void
SDL_SetupDigi(void)
{
memptr list;
word far *p,
pg;
int i;
PM_UnlockMainMem();
MM_GetPtr(&list,PMPageSize);
PM_CheckMainMem();
p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);
_fmemcpy((void far *)list,(void far *)p,PMPageSize);
pg = PMSoundStart;
for (i = 0;i PMPageSize / (sizeof(word) * 2);i++,p += 2)
{
if (pg >= ChunksInFile - 1)
break;
pg += (p[1] + (PMPageSize - 1)) / PMPageSize;
}
PM_UnlockMainMem();
MM_GetPtr((memptr *)&DigiList,i * sizeof(word) * 2);
_fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);
MM_FreePtr(&list);
NumDigi = i;
for (i = 0;i LASTSOUND;i++)
DigiMap[i] = -1;
}
// AdLib Code
///////////////////////////////////////////////////////////////////////////
//
// alOut(n,b) - Puts b in AdLib card register n
//
///////////////////////////////////////////////////////////////////////////
void
alOut(byte n,byte b)
{
asm pushf
asm cli
asm mov dx,0x388
asm mov al,[n]
asm out dx,al
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm inc dx
asm mov al,[b]
asm out dx,al
asm popf
asm dec dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
asm in al,dx
}
#if 0
///////////////////////////////////////////////////////////////////////////
//
// SDL_SetInstrument() - Puts an instrument into a generator
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)
{
byte c,m;
if (percussive)
{
c = pcarriers[which];
m = pmodifiers[which];
}
else
{
c = carriers[which];
m = modifiers[which];
}
tracks[track - 1]->inst = *inst;
tracks[track - 1]->percussive = percussive;
alOut(m + alChar,inst->mChar);
alOut(m + alScale,inst->mScale);
alOut(m + alAttack,inst->mAttack);
alOut(m + alSus,inst->mSus);
alOut(m + alWave,inst->mWave);
// Most percussive instruments only use one cell
if (c != 0xff)
{
alOut(c + alChar,inst->cChar);
alOut(c + alScale,inst->cScale);
alOut(c + alAttack,inst->cAttack);
alOut(c + alSus,inst->cSus);
alOut(c + alWave,inst->cWave);
}
alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right
}
#endif
///////////////////////////////////////////////////////////////////////////
//
// SDL_ALStopSound() - Turns off any sound effects playing through the
// AdLib card
//
///////////////////////////////////////////////////////////////////////////
#ifdef _MUSE_
void
#else
static void
#endif
SDL_ALStopSound(void)
{
asm pushf
asm cli
(long)alSound = 0;
alOut(alFreqH + 0,0);
asm popf
}
static void
SDL_AlSetFXInst(Instrument far *inst)
{
byte c,m;
m = modifiers[0];
c = carriers[0];
alOut(m + alChar,inst->mChar);
alOut(m + alScale,inst->mScale);
alOut(m + alAttack,inst->mAttack);
alOut(m + alSus,inst->mSus);
alOut(m + alWave,inst->mWave);
alOut(c + alChar,inst->cChar);
alOut(c + alScale,inst->cScale);
alOut(c + alAttack,inst->cAttack);
alOut(c + alSus,inst->cSus);
alOut(c + alWave,inst->cWave);
// Note: Switch commenting on these lines for old MUSE compatibility
// alOut(alFeedCon,inst->nConn);
alOut(alFeedCon,0);
}
///////////////////////////////////////////////////////////////////////////
//
// SDL_ALPlaySound() - Plays the specified sound on the AdLib card
//
///////////////////////////////////////////////////////////////////////////
#ifdef _MUSE_
void
#else
static void
#endif
SDL_ALPlaySound(AdLibSound far *sound)
{
Instrument far *inst;
byte huge *data;
SDL_ALStopSound();
asm pushf
asm cli
alLengthLeft = sound->common.length;
data = sound->data;
data++;
data--;
alSound = (byte far *)data;
alBlock = ((sound->block & 7) 2) | 0x20;
inst = &sound->inst;
if (!(inst->mSus | inst->cSus))
{
asm popf
Quit("SDL_ALPlaySound() - Bad instrument");
}
SDL_AlSetFXInst(&alZeroInst); // DEBUG
SDL_AlSetFXInst(inst);
asm popf
}
#if 0
///////////////////////////////////////////////////////////////////////////
//
// SDL_ALSoundService() - Plays the next sample out through the AdLib card
//
///////////////////////////////////////////////////////////////////////////
//static void
void
SDL_ALSoundService(void)
{
byte s;
if (alSound)
{
s = *alSound++;
if (!s)
alOut(alFreqH + 0,0);
else
{
alOut(alFreqL + 0,s);
alOut(alFreqH + 0,alBlock);
}
if (!(--alLengthLeft))
{
(long)alSound = 0;
alOut(alFreqH + 0,0);
SDL_SoundFinished();
}
}
}
#endif
#if 0
void
SDL_ALService(void)
{
byte a,v;
word w;
if (!sqActive)
return;
while (sqHackLen && (sqHackTime = alTimeCount))
{
w = *sqHackPtr++;
sqHackTime = alTimeCount + *sqHackPtr++;
asm mov dx,[w]
asm mov [a],dl
asm mov [v],dh
alOut(a,v);
sqHackLen -= 4;
}
alTimeCount++;
if (!sqHackLen)
{
sqHackPtr = (word far *)sqHack;
sqHackLen = sqHackSeqLen;
alTimeCount = sqHackTime = 0;
}
}
#endif
///////////////////////////////////////////////////////////////////////////
//
// SDL_ShutAL() - Shuts down the AdLib card for sound effects
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_ShutAL(void)
{
asm pushf
asm cli
alOut(alEffects,0);
alOut(alFreqH + 0,0);
SDL_AlSetFXInst(&alZeroInst);
alSound = 0;
asm popf
}
///////////////////////////////////////////////////////////////////////////
//
// SDL_CleanAL() - Totally shuts down the AdLib card
//
///////////////////////////////////////////////////////////////////////////
static void
SDL_CleanAL(void)
{
int i;
asm pushf
asm cli
alOut(alEffects,0);
for (i = 1;i 0xf5;i++)
alOut(i,0);
asm popf
}