27,16 → 27,21 |
// NeedsMusic - load music? |
// |
|
/// ///////////// /// |
/// In Kolibrios - stub |
|
#include "wl_def.h" |
#include "SDL_mixer/SDL_mixer.h" |
//#include <SDL_mixer.h> |
#if defined(GP2X_940) |
#include "gp2x/fmopl.h" |
#else |
#ifdef USE_GPL |
#include "dosbox/dbopl.h" |
#else |
#include "mame/fmopl.h" |
#endif |
#endif |
|
#pragma hdrstop |
|
#define ORIGSAMPLERATE 7042 |
|
typedef struct |
66,11 → 71,6 |
uint32_t length; |
} digiinfo; |
|
static Mix_Chunk *SoundChunks[ STARTMUSIC - STARTDIGISOUNDS]; |
static byte *SoundBuffers[STARTMUSIC - STARTDIGISOUNDS]; |
|
globalsoundpos channelSoundPos[MIX_CHANNELS]; |
|
// Global variables |
boolean AdLibPresent, |
SoundBlasterPresent,SBProPresent, |
116,1309 → 116,29 |
static int sqHackSeqLen; |
static longword sqHackTime; |
|
// STUB |
void SD_Startup(void){}; |
void SD_Shutdown(void){}; |
|
static void SDL_SoundFinished(void) |
{ |
SoundNumber = (soundnames)0; |
SoundPriority = 0; |
} |
int SD_GetChannelForDigi(int which){}; |
void SD_PositionSound(int leftvol,int rightvol){}; |
boolean SD_PlaySound(soundnames sound){}; |
void SD_SetPosition(int channel, int leftvol,int rightvol){}; |
void SD_StopSound(void){}; |
void SD_WaitSoundDone(void){}; |
|
void SD_StartMusic(int chunk){}; |
void SD_ContinueMusic(int chunk, int startoffs){}; |
void SD_MusicOn(void){}; |
void SD_FadeOutMusic(void){}; |
int SD_MusicOff(void){}; |
|
#ifdef NOTYET |
boolean SD_MusicPlaying(void){}; |
boolean SD_SetSoundMode(SDMode mode){}; |
boolean SD_SetMusicMode(SMMode mode){}; |
word SD_SoundPlaying(void){}; |
|
void SDL_turnOnPCSpeaker(word timerval); |
#pragma aux SDL_turnOnPCSpeaker = \ |
"mov al,0b6h" \ |
"out 43h,al" \ |
"mov al,bl" \ |
"out 42h,al" \ |
"mov al,bh" \ |
"out 42h,al" \ |
"in al,61h" \ |
"or al,3" \ |
"out 61h,al" \ |
parm [bx] \ |
modify exact [al] |
|
void SDL_turnOffPCSpeaker(); |
#pragma aux SDL_turnOffPCSpeaker = \ |
"in al,61h" \ |
"and al,0fch" \ |
"out 61h,al" \ |
modify exact [al] |
|
void SDL_setPCSpeaker(byte val); |
#pragma aux SDL_setPCSpeaker = \ |
"in al,61h" \ |
"and al,0fch" \ |
"or al,ah" \ |
"out 61h,al" \ |
parm [ah] \ |
modify exact [al] |
|
void inline SDL_DoFX() |
{ |
if(pcSound) |
{ |
if(*pcSound!=pcLastSample) |
{ |
pcLastSample=*pcSound; |
|
if(pcLastSample) |
SDL_turnOnPCSpeaker(pcLastSample*60); |
else |
SDL_turnOffPCSpeaker(); |
} |
pcSound++; |
pcLengthLeft--; |
if(!pcLengthLeft) |
{ |
pcSound=0; |
SoundNumber=(soundnames)0; |
SoundPriority=0; |
SDL_turnOffPCSpeaker(); |
} |
} |
|
// [adlib sound stuff removed...] |
} |
|
static void SDL_DigitizedDoneInIRQ(void); |
|
void inline SDL_DoFast() |
{ |
count_fx++; |
if(count_fx>=5) |
{ |
count_fx=0; |
|
SDL_DoFX(); |
|
count_time++; |
if(count_time>=2) |
{ |
TimeCount++; |
count_time=0; |
} |
} |
|
// [adlib music and soundsource stuff removed...] |
|
TimerCount+=TimerDivisor; |
if(*((word *)&TimerCount+1)) |
{ |
*((word *)&TimerCount+1)=0; |
t0OldService(); |
} |
else |
{ |
outp(0x20,0x20); |
} |
} |
|
// Timer 0 ISR for 7000Hz interrupts |
void __interrupt SDL_t0ExtremeAsmService(void) |
{ |
if(pcindicate) |
{ |
if(pcSound) |
{ |
SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); |
pcLengthLeft--; |
if(!pcLengthLeft) |
{ |
pcSound=0; |
SDL_turnOffPCSpeaker(); |
SDL_DigitizedDoneInIRQ(); |
} |
} |
} |
extreme++; |
if(extreme>=10) |
{ |
extreme=0; |
SDL_DoFast(); |
} |
else |
outp(0x20,0x20); |
} |
|
// Timer 0 ISR for 700Hz interrupts |
void __interrupt SDL_t0FastAsmService(void) |
{ |
SDL_DoFast(); |
} |
|
// Timer 0 ISR for 140Hz interrupts |
void __interrupt SDL_t0SlowAsmService(void) |
{ |
count_time++; |
if(count_time>=2) |
{ |
TimeCount++; |
count_time=0; |
} |
|
SDL_DoFX(); |
|
TimerCount+=TimerDivisor; |
if(*((word *)&TimerCount+1)) |
{ |
*((word *)&TimerCount+1)=0; |
t0OldService(); |
} |
else |
outp(0x20,0x20); |
} |
|
void SDL_IndicatePC(boolean ind) |
{ |
pcindicate=ind; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_SetTimer0() - Sets system timer 0 to the specified speed |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_SetTimer0(word speed) |
{ |
#ifndef TPROF // If using Borland's profiling, don't screw with the timer |
// _asm pushfd |
_asm cli |
|
outp(0x43,0x36); // Change timer 0 |
outp(0x40,(byte)speed); |
outp(0x40,speed >> 8); |
// Kludge to handle special case for digitized PC sounds |
if (TimerDivisor == (1192030 / (TickBase * 100))) |
TimerDivisor = (1192030 / (TickBase * 10)); |
else |
TimerDivisor = speed; |
|
// _asm popfd |
_asm sti |
#else |
TimerDivisor = 0x10000; |
#endif |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of |
// interrupts generated by system timer 0 per second |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_SetIntsPerSec(word ints) |
{ |
TimerRate = ints; |
SDL_SetTimer0(1192030 / ints); |
} |
|
static void |
SDL_SetTimerSpeed(void) |
{ |
word rate; |
void (_interrupt *isr)(void); |
|
if ((DigiMode == sds_PC) && DigiPlaying) |
{ |
rate = TickBase * 100; |
isr = SDL_t0ExtremeAsmService; |
} |
else if ((MusicMode == smm_AdLib) || ((DigiMode == sds_SoundSource) && DigiPlaying) ) |
{ |
rate = TickBase * 10; |
isr = SDL_t0FastAsmService; |
} |
else |
{ |
rate = TickBase * 2; |
isr = SDL_t0SlowAsmService; |
} |
|
if (rate != TimerRate) |
{ |
_dos_setvect(8,isr); |
SDL_SetIntsPerSec(rate); |
TimerRate = rate; |
} |
} |
|
// |
// PC Sound code |
// |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCPlaySample() - Plays the specified sample on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCPlaySample(byte *data,longword len,boolean inIRQ) |
{ |
if(!inIRQ) |
{ |
// _asm pushfd |
_asm cli |
} |
|
SDL_IndicatePC(true); |
|
pcLengthLeft = len; |
pcSound = (volatile byte *)data; |
|
if(!inIRQ) |
{ |
// _asm popfd |
_asm sti |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCStopSample() - Stops a sample playing on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCStopSampleInIRQ(void) |
{ |
pcSound = 0; |
|
SDL_IndicatePC(false); |
|
_asm in al,0x61 // Turn the speaker off |
_asm and al,0xfd // ~2 |
_asm out 0x61,al |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCPlaySound() - Plays the specified sound on the PC speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCPlaySound(PCSound *sound) |
{ |
// _asm pushfd |
_asm cli |
|
pcLastSample = -1; |
pcLengthLeft = sound->common.length; |
pcSound = sound->data; |
|
// _asm popfd |
_asm sti |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
#ifdef _MUSE_ |
void |
#else |
static void |
#endif |
SDL_PCStopSound(void) |
{ |
// _asm pushfd |
_asm cli |
|
pcSound = 0; |
|
_asm in al,0x61 // Turn the speaker off |
_asm and al,0xfd // ~2 |
_asm out 0x61,al |
|
// _asm popfd |
_asm sti |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ShutPC() - Turns off the pc speaker |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ShutPC(void) |
{ |
// _asm pushfd |
_asm cli |
|
pcSound = 0; |
|
_asm in al,0x61 // Turn the speaker & gate off |
_asm and al,0xfc // ~3 |
_asm out 0x61,al |
|
// _asm popfd |
_asm sti |
} |
|
#endif |
|
void |
SD_StopDigitized(void) |
{ |
DigiPlaying = false; |
DigiNumber = (soundnames) 0; |
DigiPriority = 0; |
SoundPositioned = false; |
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
SDL_SoundFinished(); |
|
switch (DigiMode) |
{ |
case sds_PC: |
// SDL_PCStopSampleInIRQ(); |
break; |
case sds_SoundBlaster: |
// SDL_SBStopSampleInIRQ(); |
Mix_HaltChannel(-1); |
break; |
} |
} |
|
int SD_GetChannelForDigi(int which) |
{ |
if(DigiChannel[which] != -1) return DigiChannel[which]; |
|
int channel = Mix_GroupAvailable(1); |
if(channel == -1) channel = Mix_GroupOldest(1); |
if(channel == -1) // All sounds stopped in the meantime? |
return Mix_GroupAvailable(1); |
return channel; |
} |
|
void SD_SetPosition(int channel, 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); |
Mix_SetPanning(channel, ((15 - leftpos) << 4) + 15, |
((15 - rightpos) << 4) + 15); |
break; |
} |
} |
|
Sint16 GetSample(float csample, byte *samples, int size) |
{ |
float s0=0, s1=0, s2=0; |
int cursample = (int) csample; |
float sf = csample - (float) cursample; |
|
if(cursample-1 >= 0) s0 = (float) (samples[cursample-1] - 128); |
s1 = (float) (samples[cursample] - 128); |
if(cursample+1 < size) s2 = (float) (samples[cursample+1] - 128); |
|
float val = s0*sf*(sf-1)/2 - s1*(sf*sf-1) + s2*(sf+1)*sf/2; |
int32_t intval = (int32_t) (val * 256); |
if(intval < -32768) intval = -32768; |
else if(intval > 32767) intval = 32767; |
return (Sint16) intval; |
} |
|
void SD_PrepareSound(int which) |
{ |
if(DigiList == NULL) |
Quit("SD_PrepareSound(%i): DigiList not initialized!\n", which); |
|
int page = DigiList[which].startpage; |
int size = DigiList[which].length; |
|
byte *origsamples = PM_GetSound(page); |
if(origsamples + size >= PM_GetEnd()) |
Quit("SD_PrepareSound(%i): Sound reaches out of page file!\n", which); |
|
int destsamples = (int) ((float) size * (float) param_samplerate |
/ (float) ORIGSAMPLERATE); |
|
byte *wavebuffer = (byte *) malloc(sizeof(headchunk) + sizeof(wavechunk) |
+ destsamples * 2); // dest are 16-bit samples |
if(wavebuffer == NULL) |
Quit("Unable to allocate wave buffer for sound %i!\n", which); |
|
headchunk head = {{'R','I','F','F'}, 0, {'W','A','V','E'}, |
{'f','m','t',' '}, 0x10, 0x0001, 1, param_samplerate, param_samplerate*2, 2, 16}; |
wavechunk dhead = {{'d', 'a', 't', 'a'}, destsamples*2}; |
head.filelenminus8 = sizeof(head) + destsamples*2; // (sizeof(dhead)-8 = 0) |
memcpy(wavebuffer, &head, sizeof(head)); |
memcpy(wavebuffer+sizeof(head), &dhead, sizeof(dhead)); |
|
// alignment is correct, as wavebuffer comes from malloc |
// and sizeof(headchunk) % 4 == 0 and sizeof(wavechunk) % 4 == 0 |
Sint16 *newsamples = (Sint16 *)(void *) (wavebuffer + sizeof(headchunk) |
+ sizeof(wavechunk)); |
float cursample = 0.F; |
float samplestep = (float) ORIGSAMPLERATE / (float) param_samplerate; |
for(int i=0; i<destsamples; i++, cursample+=samplestep) |
{ |
newsamples[i] = GetSample((float)size * (float)i / (float)destsamples, |
origsamples, size); |
} |
SoundBuffers[which] = wavebuffer; |
|
SoundChunks[which] = Mix_LoadWAV_RW(SDL_RWFromMem(wavebuffer, |
sizeof(headchunk) + sizeof(wavechunk) + destsamples * 2), 1); |
} |
|
int SD_PlayDigitized(word which,int leftpos,int rightpos) |
{ |
if (!DigiMode) |
return 0; |
|
if (which >= NumDigi) |
Quit("SD_PlayDigitized: bad sound number %i", which); |
|
int channel = SD_GetChannelForDigi(which); |
SD_SetPosition(channel, leftpos,rightpos); |
|
DigiPlaying = true; |
|
Mix_Chunk *sample = SoundChunks[which]; |
if(sample == NULL) |
{ |
printf("SoundChunks[%i] is NULL!\n", which); |
return 0; |
} |
|
if(Mix_PlayChannel(channel, sample, 0) == -1) |
{ |
printf("Unable to play sound: %s\n", Mix_GetError()); |
return 0; |
} |
|
return channel; |
} |
|
void SD_ChannelFinished(int channel) |
{ |
channelSoundPos[channel].valid = 0; |
} |
|
void |
SD_SetDigiDevice(SDSMode mode) |
{ |
boolean devicenotpresent; |
|
if (mode == DigiMode) |
return; |
|
SD_StopDigitized(); |
|
devicenotpresent = false; |
switch (mode) |
{ |
case sds_SoundBlaster: |
if (!SoundBlasterPresent) |
devicenotpresent = true; |
break; |
} |
|
if (!devicenotpresent) |
{ |
DigiMode = mode; |
|
#ifdef NOTYET |
SDL_SetTimerSpeed(); |
#endif |
} |
} |
|
void |
SDL_SetupDigi(void) |
{ |
// Correct padding enforced by PM_Startup() |
word *soundInfoPage = (word *) (void *) PM_GetPage(ChunksInFile-1); |
NumDigi = (word) PM_GetPageSize(ChunksInFile - 1) / 4; |
|
DigiList = (digiinfo *) malloc(NumDigi * sizeof(digiinfo)); |
int i; |
for(i = 0; i < NumDigi; i++) |
{ |
// Calculate the size of the digi from the sizes of the pages between |
// the start page and the start page of the next sound |
|
DigiList[i].startpage = soundInfoPage[i * 2]; |
if((int) DigiList[i].startpage >= ChunksInFile - 1) |
{ |
NumDigi = i; |
break; |
} |
|
int lastPage; |
if(i < NumDigi - 1) |
{ |
lastPage = soundInfoPage[i * 2 + 2]; |
if(lastPage == 0 || lastPage + PMSoundStart > ChunksInFile - 1) lastPage = ChunksInFile - 1; |
else lastPage += PMSoundStart; |
} |
else lastPage = ChunksInFile - 1; |
|
int size = 0; |
for(int page = PMSoundStart + DigiList[i].startpage; page < lastPage; page++) |
size += PM_GetPageSize(page); |
|
// Don't include padding of sound info page, if padding was added |
if(lastPage == ChunksInFile - 1 && PMSoundInfoPagePadded) size--; |
|
// Patch lower 16-bit of size with size from sound info page. |
// The original VSWAP contains padding which is included in the page size, |
// but not included in the 16-bit size. So we use the more precise value. |
if((size & 0xffff0000) != 0 && (size & 0xffff) < soundInfoPage[i * 2 + 1]) |
size -= 0x10000; |
size = (size & 0xffff0000) | soundInfoPage[i * 2 + 1]; |
|
DigiList[i].length = size; |
} |
|
for(i = 0; i < LASTSOUND; i++) |
{ |
DigiMap[i] = -1; |
DigiChannel[i] = -1; |
} |
} |
|
// AdLib Code |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ALStopSound() - Turns off any sound effects playing through the |
// AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ALStopSound(void) |
{ |
alSound = 0; |
alOut(alFreqH + 0, 0); |
} |
|
static void |
SDL_AlSetFXInst(Instrument *inst) |
{ |
byte c,m; |
|
m = 0; // modulator cell for channel 0 |
c = 3; // carrier cell for channel 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 |
// alOutInIRQ(alFeedCon,inst->nConn); |
alOut(alFeedCon,0); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ALPlaySound() - Plays the specified sound on the AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ALPlaySound(AdLibSound *sound) |
{ |
Instrument *inst; |
byte *data; |
|
SDL_ALStopSound(); |
|
alLengthLeft = sound->common.length; |
data = sound->data; |
alBlock = ((sound->block & 7) << 2) | 0x20; |
inst = &sound->inst; |
|
if (!(inst->mSus | inst->cSus)) |
{ |
Quit("SDL_ALPlaySound() - Bad instrument"); |
} |
|
SDL_AlSetFXInst(inst); |
alSound = (byte *)data; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_ShutAL() - Shuts down the AdLib card for sound effects |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_ShutAL(void) |
{ |
alSound = 0; |
alOut(alEffects,0); |
alOut(alFreqH + 0,0); |
SDL_AlSetFXInst(&alZeroInst); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_CleanAL() - Totally shuts down the AdLib card |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_CleanAL(void) |
{ |
int i; |
|
alOut(alEffects,0); |
for (i = 1; i < 0xf5; i++) |
alOut(i, 0); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_StartAL() - Starts up the AdLib card for sound effects |
// |
/////////////////////////////////////////////////////////////////////////// |
static void |
SDL_StartAL(void) |
{ |
alOut(alEffects, 0); |
SDL_AlSetFXInst(&alZeroInst); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster |
// emulating an AdLib) present |
// |
/////////////////////////////////////////////////////////////////////////// |
static boolean |
SDL_DetectAdLib(void) |
{ |
for (int 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; |
} |
|
//////////////////////////////////////////////////////////////////////////// |
// |
// 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 = (soundnames) 0; |
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(); |
|
if ((mode == sdm_AdLib) && !AdLibPresent) |
mode = sdm_PC; |
|
switch (mode) |
{ |
case sdm_Off: |
tableoffset = STARTADLIBSOUNDS; |
result = true; |
break; |
case sdm_PC: |
tableoffset = STARTPCSOUNDS; |
result = true; |
break; |
case sdm_AdLib: |
tableoffset = STARTADLIBSOUNDS; |
if (AdLibPresent) |
result = true; |
break; |
default: |
Quit("SD_SetSoundMode: Invalid sound mode %i", mode); |
return false; |
} |
SoundTable = &audiosegs[tableoffset]; |
|
if (result && (mode != SoundMode)) |
{ |
SDL_ShutDevice(); |
SoundMode = mode; |
SDL_StartDevice(); |
} |
|
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()) |
SDL_Delay(5); |
|
switch (mode) |
{ |
case smm_Off: |
result = true; |
break; |
case smm_AdLib: |
if (AdLibPresent) |
result = true; |
break; |
} |
|
if (result) |
MusicMode = mode; |
|
// SDL_SetTimerSpeed(); |
|
return(result); |
} |
|
int numreadysamples = 0; |
byte *curAlSound = 0; |
byte *curAlSoundPtr = 0; |
longword curAlLengthLeft = 0; |
int soundTimeCounter = 5; |
int samplesPerMusicTick; |
|
void SDL_IMFMusicPlayer(void *udata, Uint8 *stream, int len) |
{ |
int stereolen = len>>1; |
int sampleslen = stereolen>>1; |
INT16 *stream16 = (INT16 *) (void *) stream; // expect correct alignment |
|
while(1) |
{ |
if(numreadysamples) |
{ |
if(numreadysamples<sampleslen) |
{ |
YM3812UpdateOne(0, stream16, numreadysamples); |
stream16 += numreadysamples*2; |
sampleslen -= numreadysamples; |
} |
else |
{ |
YM3812UpdateOne(0, stream16, sampleslen); |
numreadysamples -= sampleslen; |
return; |
} |
} |
soundTimeCounter--; |
if(!soundTimeCounter) |
{ |
soundTimeCounter = 5; |
if(curAlSound != alSound) |
{ |
curAlSound = curAlSoundPtr = alSound; |
curAlLengthLeft = alLengthLeft; |
} |
if(curAlSound) |
{ |
if(*curAlSoundPtr) |
{ |
alOut(alFreqL, *curAlSoundPtr); |
alOut(alFreqH, alBlock); |
} |
else alOut(alFreqH, 0); |
curAlSoundPtr++; |
curAlLengthLeft--; |
if(!curAlLengthLeft) |
{ |
curAlSound = alSound = 0; |
SoundNumber = (soundnames) 0; |
SoundPriority = 0; |
alOut(alFreqH, 0); |
} |
} |
} |
if(sqActive) |
{ |
do |
{ |
if(sqHackTime > alTimeCount) break; |
sqHackTime = alTimeCount + *(sqHackPtr+1); |
alOut(*(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1)); |
sqHackPtr += 2; |
sqHackLen -= 4; |
} |
while(sqHackLen>0); |
alTimeCount++; |
if(!sqHackLen) |
{ |
sqHackPtr = sqHack; |
sqHackLen = sqHackSeqLen; |
sqHackTime = 0; |
alTimeCount = 0; |
} |
} |
numreadysamples = samplesPerMusicTick; |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// 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; |
|
if(Mix_OpenAudio(param_samplerate, AUDIO_S16, 2, param_audiobuffer)) |
{ |
printf("Unable to open audio: %s\n", Mix_GetError()); |
return; |
} |
|
Mix_ReserveChannels(2); // reserve player and boss weapon channels |
Mix_GroupChannels(2, MIX_CHANNELS-1, 1); // group remaining channels |
|
// Init music |
|
samplesPerMusicTick = param_samplerate / 700; // SDL_t0FastAsmService played at 700Hz |
|
if(YM3812Init(1,3579545,param_samplerate)) |
{ |
printf("Unable to create virtual OPL!!\n"); |
} |
|
for(i=1;i<0xf6;i++) |
YM3812Write(0,i,0); |
|
YM3812Write(0,1,0x20); // Set WSE=1 |
// YM3812Write(0,8,0); // Set CSM=0 & SEL=0 // already set in for statement |
|
Mix_HookMusic(SDL_IMFMusicPlayer, 0); |
Mix_ChannelFinished(SD_ChannelFinished); |
AdLibPresent = true; |
SoundBlasterPresent = true; |
|
alTimeCount = 0; |
|
SD_SetSoundMode(sdm_Off); |
SD_SetMusicMode(smm_Off); |
|
SDL_SetupDigi(); |
|
SD_Started = true; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// 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(); |
|
for(int i = 0; i < STARTMUSIC - STARTDIGISOUNDS; i++) |
{ |
if(SoundChunks[i]) Mix_FreeChunk(SoundChunks[i]); |
if(SoundBuffers[i]) free(SoundBuffers[i]); |
} |
|
free(DigiList); |
|
SD_Started = false; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// 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 *s; |
int lp,rp; |
|
lp = LeftPosition; |
rp = RightPosition; |
LeftPosition = 0; |
RightPosition = 0; |
|
ispos = nextsoundpos; |
nextsoundpos = false; |
|
if (sound == -1 || (DigiMode == sds_Off && SoundMode == sdm_Off)) |
return 0; |
|
s = (SoundCommon *) SoundTable[sound]; |
|
if ((SoundMode != sdm_Off) && !s) |
Quit("SD_PlaySound() - Uncached sound"); |
|
if ((DigiMode != sds_Off) && (DigiMap[sound] != -1)) |
{ |
if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
{ |
#ifdef NOTYET |
if (s->priority < SoundPriority) |
return 0; |
|
SDL_PCStopSound(); |
|
SD_PlayDigitized(DigiMap[sound],lp,rp); |
SoundPositioned = ispos; |
SoundNumber = sound; |
SoundPriority = s->priority; |
#else |
return 0; |
#endif |
} |
else |
{ |
#ifdef NOTYET |
if (s->priority < DigiPriority) |
return(false); |
#endif |
|
int channel = SD_PlayDigitized(DigiMap[sound], lp, rp); |
SoundPositioned = ispos; |
DigiNumber = sound; |
DigiPriority = s->priority; |
return channel + 1; |
} |
|
return(true); |
} |
|
if (SoundMode == sdm_Off) |
return 0; |
|
if (!s->length) |
Quit("SD_PlaySound() - Zero length sound"); |
if (s->priority < SoundPriority) |
return 0; |
|
switch (SoundMode) |
{ |
case sdm_PC: |
// SDL_PCPlaySound((PCSound *)s); |
break; |
case sdm_AdLib: |
SDL_ALPlaySound((AdLibSound *)s); |
break; |
} |
|
SoundNumber = sound; |
SoundPriority = s->priority; |
|
return 0; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// 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()) |
SDL_Delay(5); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_MusicOn() - turns on the sequencer |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_MusicOn(void) |
{ |
sqActive = true; |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_MusicOff() - turns off the sequencer and any playing notes |
// returns the last music offset for music continue |
// |
/////////////////////////////////////////////////////////////////////////// |
int |
SD_MusicOff(void) |
{ |
word i; |
|
sqActive = false; |
switch (MusicMode) |
{ |
case smm_AdLib: |
alOut(alEffects, 0); |
for (i = 0;i < sqMaxTracks;i++) |
alOut(alFreqH + i + 1, 0); |
break; |
} |
|
return (int) (sqHackPtr-sqHack); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// SD_StartMusic() - starts playing the music pointed to |
// |
/////////////////////////////////////////////////////////////////////////// |
void |
SD_StartMusic(int chunk) |
{ |
SD_MusicOff(); |
|
if (MusicMode == smm_AdLib) |
{ |
int32_t chunkLen = CA_CacheAudioChunk(chunk); |
sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
else sqHackLen = sqHackSeqLen = *sqHack++; |
sqHackPtr = sqHack; |
sqHackTime = 0; |
alTimeCount = 0; |
SD_MusicOn(); |
} |
} |
|
void |
SD_ContinueMusic(int chunk, int startoffs) |
{ |
SD_MusicOff(); |
|
if (MusicMode == smm_AdLib) |
{ |
int32_t chunkLen = CA_CacheAudioChunk(chunk); |
sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
else sqHackLen = sqHackSeqLen = *sqHack++; |
sqHackPtr = sqHack; |
|
if(startoffs >= sqHackLen) |
{ |
Quit("SD_StartMusic: Illegal startoffs provided!"); |
} |
|
// fast forward to correct position |
// (needed to reconstruct the instruments) |
|
for(int i = 0; i < startoffs; i += 2) |
{ |
byte reg = *(byte *)sqHackPtr; |
byte val = *(((byte *)sqHackPtr) + 1); |
if(reg >= 0xb1 && reg <= 0xb8) val &= 0xdf; // disable play note flag |
else if(reg == 0xbd) val &= 0xe0; // disable drum flags |
|
alOut(reg,val); |
sqHackPtr += 2; |
sqHackLen -= 4; |
} |
sqHackTime = 0; |
alTimeCount = 0; |
|
SD_MusicOn(); |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// |
// 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 = sqActive; |
break; |
default: |
result = false; |
break; |
} |
|
return(result); |
} |
void SD_SetDigiDevice(SDSMode){}; |
void SD_PrepareSound(int which){}; |
int SD_PlayDigitized(word which,int leftpos,int rightpos){}; |
void SD_StopDigitized(void){}; |