+#else\r
+#include "src/lib/16_head.h"\r
+#endif\r
+#pragma hdrstop\r
+#pragma warn -pia\r
+\r
+#define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}\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
+/*extern*/ void interrupt SDL_t0ExtremeAsmService(void);//,\r
+// SDL_t0FastAsmService(void),\r
+// SDL_t0SlowAsmService(void);\r
+ void SDL_IndicatePC(boolean on),\r
+ SDL_DigitizedDoneInIRQ();\r
+\r
+// Global variables\r
+ boolean AdLibPresent,\r
+ NeedsDigitized,NeedsMusic,\r
+ SoundPositioned;\r
+ SDMode SoundMode;\r
+ SMMode MusicMode;\r
+ SDSMode DigiMode;\r
+ dword TimeCount;\r
+ word HackCount;\r
+ word *SoundTable; // Really * _seg *SoundTable, but that don't work\r
+ boolean ssIsTandy;\r
+ int DigiMap[LASTSOUND];\r
+\r
+// Internal variables\r
+static boolean SD_Started;\r
+ boolean nextsoundpos;\r
+ word/*boolean_+*/ TimerDone;\r
+ word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;\r
+ dword TimerDivisor,TimerCount;\r
+static char *ParmStrings[] =\r
+ {\r
+ "noal",\r
+ nil\r
+ };\r
+static void (*SoundUserHook)(void);\r
+ soundnames SoundNumber,DigiNumber;\r
+ word SoundPriority,DigiPriority;\r
+ int LeftPosition,RightPosition;\r
+ void interrupt (*t0OldService)(void);\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
+// PC Sound variables\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
+ dword alLengthLeft;\r
+ dword alTimeCount;\r
+ Instrument alZeroInst;\r
+\r
+// This table maps channel numbers to carrier and modulator op cells\r
+static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},\r
+ modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},\r
+// This table maps percussive voice numbers to op cells\r
+ pcarriers[5] = {19,0xff,0xff,0xff,0xff},\r
+ pmodifiers[5] = {16,17,18,20,21};\r
+\r
+// Sequencer variables\r
+ boolean sqActive;\r
+static word alFXReg;\r
+static ActiveTrack *tracks[sqMaxTracks];//,\r
+//-- mytracks[sqMaxTracks];\r
+//--static word sqMode,sqFadeStep;\r
+ word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;\r
+ long sqHackTime;\r
+\r
+// Internal routines\r
+ void SDL_DigitizedDone(void);\r
+\r
+//Assembly functions\r
+boolean alNoIRQ;\r
+\r
+int count_time=0;\r
+int count_fx=0;\r
+int extreme=0;\r
+\r
+void SDL_turnOnPCSpeaker(word timerval)\r
+{\r
+ __asm {\r
+ mov bx,timerval\r
+ mov al,0b6h\r
+ out 43h,al\r
+ mov al,bl\r
+ out 42h,al\r
+ mov al,bh\r
+ out 42h,al\r
+ in al,61h\r
+ or al,3\r
+ out 61h,al\r
+ }\r
+}\r
+\r
+void SDL_turnOffPCSpeaker()\r
+{\r
+ __asm {\r
+ in al,61h\r
+ and al,0fch\r
+ out 61h,al\r
+ }\r
+}\r
+\r
+void SDL_setPCSpeaker(byte val)\r
+{\r
+ __asm {\r
+ mov al,val\r
+ in al,61h\r
+ and al,0fch\r
+ or al,ah\r
+ out 61h,al\r
+ }\r
+}\r
+\r
+void SDL_DoFX()\r
+{\r
+ if(pcSound)\r
+ {\r
+ if(*pcSound!=pcLastSample)\r
+ {\r
+ pcLastSample=*pcSound;\r
+\r
+ if(pcLastSample)\r
+ SDL_turnOnPCSpeaker(pcLastSample*60);\r
+ else\r
+ SDL_turnOffPCSpeaker();\r
+ }\r
+ pcSound++;\r
+ pcLengthLeft--;\r
+ if(!pcLengthLeft)\r
+ {\r
+ pcSound=0;\r
+ SoundNumber=(soundnames)0;\r
+ SoundPriority=0;\r
+ SDL_turnOffPCSpeaker();\r
+ }\r
+ }\r
+\r
+ if(alSound && !alNoIRQ)\r
+ {\r
+ if(*alSound)\r
+ {\r
+ alOut/*InIRQ*/(alFreqL,*alSound);\r
+ alOut/*InIRQ*/(alFreqH,alBlock);\r
+ }\r
+ else alOut/*InIRQ*/(alFreqH,0);\r
+ alSound++;\r
+ alLengthLeft--;\r
+ if(!alLengthLeft)\r
+ {\r
+ alSound=0;\r
+ SoundNumber=(soundnames)0;\r
+ SoundPriority=0;\r
+ alOut/*InIRQ*/(alFreqH,0);\r
+ }\r
+ }\r
+\r
+}\r
+\r
+void SDL_DoFast()\r
+{\r
+ count_fx++;\r
+ if(count_fx>=5)\r
+ {\r
+ count_fx=0;\r
+\r
+ SDL_DoFX();\r
+\r
+ count_time++;\r
+ if(count_time>=2)\r
+ {\r
+ TimeCount++;\r
+ count_time=0;\r
+ }\r
+ }\r
+\r
+ if(sqActive && !alNoIRQ)\r
+ {\r
+ if(sqHackLen)\r
+ {\r
+ do\r
+ {\r
+ if(sqHackTime>alTimeCount) break;\r
+ sqHackTime=alTimeCount+*(sqHackPtr+1);\r
+ alOut/*InIRQ*/(*(byte *)sqHackPtr,*(((byte *)sqHackPtr)+1));\r
+ sqHackPtr+=2;\r
+ sqHackLen-=4;\r
+ }\r
+ while(sqHackLen);\r
+ }\r
+ alTimeCount++;\r
+ if(!sqHackLen)\r
+ {\r
+ sqHackPtr=sqHack;\r
+ sqHackLen=sqHackSeqLen;\r
+ alTimeCount=0;\r
+ sqHackTime=0;\r
+ }\r
+ }\r
+\r
+//SS if(ssSample)\r
+//SS {\r
+//SS if(!(inp(ssStatus)&0x40))\r
+//SS {\r
+//SS outp(ssData,*ssSample++);\r
+//SS outp(ssControl,ssOff);\r
+//SS __asm push ax\r
+//SS __asm pop ax\r
+//SS outp(ssControl,ssOn);\r
+//SS __asm push ax\r
+//SS __asm pop ax\r
+//SS ssLengthLeft--;\r
+//SS if(!ssLengthLeft)\r
+//SS {\r
+//SS ssSample=0;\r
+//SS SDL_DigitizedDoneInIRQ();\r
+//SS }\r
+//SS }\r
+//SS }\r
+\r
+ TimerCount+=TimerDivisor;\r
+ if(*((word *)&TimerCount+1))\r
+ {\r
+ *((word *)&TimerCount+1)=0;\r
+ t0OldService();\r
+ }\r
+ else\r
+ {\r
+ outp(0x20,0x20);\r
+ }\r
+}\r
+\r
+// Timer 0 ISR for 700Hz interrupts\r
+void interrupt SDL_t0FastAsmService(void)\r
+{\r
+ SDL_DoFast();\r
+}\r
+\r
+// Timer 0 ISR for 140Hz interrupts\r
+void interrupt SDL_t0SlowAsmService(void)\r
+{\r
+ count_time++;\r
+ if(count_time>=2)\r
+ {\r
+ TimeCount++;\r
+ count_time=0;\r
+ }\r
+\r
+ SDL_DoFX();\r
+\r
+ TimerCount+=TimerDivisor;\r
+ if(*((word *)&TimerCount+1))\r
+ {\r
+ *((word *)&TimerCount+1)=0;\r
+ t0OldService();\r
+ }\r
+ else\r
+ outp(0x20,0x20);\r
+}\r
+\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SetTimer0() - Sets system timer 0 to the specified speed\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#pragma argsused\r
+static void\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
+#else\r
+ TimerDivisor = 0x10000;\r
+#endif\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of\r
+// interrupts generated by system timer 0 per second\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_SetIntsPerSec(word ints)\r
+{\r
+ TimerRate = ints;\r
+ SDL_SetTimer0(1192030 / ints);\r
+}\r
+\r
+#ifndef SD_USECATA3DSETTIMERSPEED\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
+#else\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
+#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\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
+void interrupt\r
+SDL_TimingService(void)\r
+{\r
+ //TimerVal = _CX;\r
+ __asm {\r
+ mov TimerVal,cx\r
+ }\r
+ TimerDone = 1;\r
+\r
+ outportb(0x20,0x20); // Ack interrupt\r
+}\r
+#ifdef SD_USECATA3DSETTIMERSPEED\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_InitDelay(void)\r
+{\r
+ int i;\r
+ word timer;\r
+\r
+//++++ setvect(8,SDL_TimingService); // Set to my timer 0 ISR\r
+\r
+ SDL_SetIntsPerSec(1000); // Time 1ms\r
+\r
+ for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times\r
+ {\r
+ __asm {\r
+ xor dx,dx // Zero DX\r
+ mov cx,0xffff // Put starting value in CX\r
+ mov [TimerDone],cx // TimerDone = false - 1\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+startloop:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ or [TimerDone],0\r
+ jnz startloop // Make sure we're at the start\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+loop_:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ test [TimerDone],1 // See if TimerDone flag got hit\r
+ jnz done // Yep - drop out of the loop\r
+ loop loop_\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+done:\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\r
+\r
+ if (0xffff - TimerVal > timer)\r
+ timer = 0xffff - TimerVal;\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
+ SDL_SetTimer0(0); // Reset timer 0\r
+\r
+ setvect(8,t0OldService); // Set back to old ISR\r
+}\r
+#endif\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_Delay() - Delays the specified amount of time\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_Delay(word delay)\r
+{\r
+ if (!delay)\r
+ return;\r
+\r
+ __asm {\r
+ mov cx,[delay]\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+loop_:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ test [TimerDone],0 // Useless code - just for timing equivilency\r
+ jnz done\r
+ loop loop_\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+done:\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\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,dword 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
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_PCPlaySound(PCSound far *sound)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ pcLastSample = -1;\r
+ pcLengthLeft = sound->common.length;\r
+ pcSound = sound->data;\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_PCStopSound(void)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ /*(long)*/pcSound = 0;\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_PCService() - Handles playing the next sample in a PC sound\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_PCService(void)\r
+{\r
+ byte s;\r
+ word t;\r
+\r
+ if (pcSound)\r
+ {\r
+ s = *pcSound++;\r
+ if (s != pcLastSample)\r
+ {\r
+ asm pushf\r
+ asm cli\r
+\r
+ pcLastSample = s;\r
+ if (s) // We have a frequency!\r
+ {\r
+ t = pcSoundLookup[s];\r
+ asm mov bx,[t]\r
+\r
+ asm mov al,0xb6 // Write to channel 2 (speaker) timer\r
+ asm out 43h,al\r
+ asm mov al,bl\r
+ asm out 42h,al // Low byte\r
+ asm mov al,bh\r
+ asm out 42h,al // High byte\r
+\r
+ asm in al,0x61 // Turn the speaker & gate on\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
+\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, global_game_variables_t *gvar)\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(gvar->pm.fi.PMSoundStart + page,pml_Locked, gvar);\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
+//SS case sds_SoundSource:\r
+//SS SDL_SSPlaySample(addr,len);\r
+//SS break;\r
+//SB case sds_SoundBlaster:\r
+//SB SDL_SBPlaySample(addr,len);\r
+//SB break;\r
+ }\r
+}\r
+\r
+void\r
+SD_StopDigitized(global_game_variables_t *gvar)\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
+//SS case sds_SoundSource:\r
+//SS SDL_SSStopSample();\r
+//SS break;\r
+//SB case sds_SoundBlaster:\r
+//SB SDL_SBStopSample();\r
+//SB break;\r
+ }\r
+\r
+asm popf\r
+\r
+ for (i = DigiLastStart;i < DigiLastEnd;i++)\r
+ PM_SetPageLock(i + gvar->pm.fi.PMSoundStart,pml_Unlocked, gvar);\r
+ DigiLastStart = 1;\r
+ DigiLastEnd = 0;\r
+}\r
+\r
+void\r
+SD_Poll(global_game_variables_t *gvar)\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++, gvar);\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, global_game_variables_t *gvar)\r
+{\r
+ if\r
+ (\r
+ (leftpos < 0)\r
+ || (leftpos > 15)\r
+ || (rightpos < 0)\r
+ || (rightpos > 15)\r
+ || ((leftpos == 15) && (rightpos == 15))\r
+ )\r
+ Quit(gvar, "SD_SetPosition: Illegal position");\r
+\r
+ switch (DigiMode)\r
+ {\r
+//SB case sds_SoundBlaster:\r
+//SB SDL_PositionSBP(leftpos,rightpos);\r
+//SB break;\r
+ }\r
+}\r
+\r
+void\r
+SD_PlayDigitized(word which,int leftpos,int rightpos, global_game_variables_t *gvar)\r
+{\r
+ word len;\r
+ memptr addr;\r
+\r
+ if (!DigiMode)\r
+ return;\r
+\r
+ SD_StopDigitized(gvar);\r
+ if (which >= NumDigi)\r
+ Quit(gvar, "SD_PlayDigitized: bad sound number");\r
+\r
+ SD_SetPosition(leftpos,rightpos, gvar);\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++, gvar);\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(gvar);\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
+ {\r
+ SDL_SoundFinished();\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, global_game_variables_t *gvar)\r
+{\r
+ boolean devicenotpresent;\r
+\r
+ if (mode == DigiMode)\r
+ return;\r
+\r
+ SD_StopDigitized(gvar);\r
+\r
+ devicenotpresent = false;\r
+//SBSS switch (mode)\r
+//SBSS {\r
+//SB case sds_SoundBlaster:\r
+//SB if (!SoundBlasterPresent)\r
+//SB {\r
+//SB if (SoundSourcePresent)\r
+//SB mode = sds_SoundSource;\r
+//SB else\r
+//SB devicenotpresent = true;\r
+//SB }\r
+//SB break;\r
+//SS case sds_SoundSource:\r
+//SS if (!SoundSourcePresent)\r
+//SS devicenotpresent = true;\r
+//SS break;\r
+//SBSS }\r
+\r
+ if (!devicenotpresent)\r
+ {\r
+//SS if (DigiMode == sds_SoundSource)\r
+//SS SDL_ShutSS();\r
+\r
+ DigiMode = mode;\r
+\r
+//SS if (mode == sds_SoundSource)\r
+//SS SDL_StartSS();\r
+\r
+ SDL_SetTimerSpeed();\r
+ }\r
+}\r
+\r
+void\r
+SDL_SetupDigi(global_game_variables_t *gvar)\r
+{\r
+ memptr list;\r
+ word far *p,\r
+ pg;\r
+ int i;\r
+\r
+ PM_UnlockMainMem(gvar);\r
+ MM_GetPtr(&list,PMPageSize, gvar);\r
+ PM_CheckMainMem(gvar);\r
+ p = (word far *)MK_FP(PM_GetPage(gvar->pm.fi.ChunksInFile - 1, gvar),0);\r
+ _fmemcpy((void far *)list,(void far *)p,PMPageSize);\r
+ pg = gvar->pm.fi.PMSoundStart;\r
+ for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2)\r
+ {\r
+ if (pg >= gvar->pm.fi.ChunksInFile - 1)\r
+ break;\r
+ pg += (p[1] + (PMPageSize - 1)) / PMPageSize;\r
+ }\r
+ PM_UnlockMainMem(gvar);\r
+ MM_GetPtr(MEMPTRCONV DigiList,i * sizeof(word) * 2, gvar);\r
+ _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);\r
+ MM_FreePtr(&list, gvar);\r
+ NumDigi = i;\r
+\r
+ for (i = 0;i < LASTSOUND;i++)\r
+ DigiMap[i] = -1;\r
+}\r
+\r
+// AdLib Code\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// alOut(n,b) - Puts b in AdLib card register n\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+alOut(byte n,byte b)\r
+{\r
+asm pushf\r
+asm cli\r
+\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
+#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
+\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
+#endif\r
+}\r
+\r
+//#if 0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SetInstrument() - Puts an instrument into a generator\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+//static void\r
+void\r
+SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)\r
+{\r
+ byte c,m;\r
+\r
+ if (percussive)\r
+ {\r
+ c = pcarriers[which];\r
+ m = pmodifiers[which];\r
+ }\r
+ else\r
+ {\r
+ c = carriers[which];\r
+ m = modifiers[which];\r
+ }\r
+\r
+ tracks[track - 1]->inst = *inst;\r
+ tracks[track - 1]->percussive = percussive;\r
+\r
+ alOut(m + alChar,inst->mChar);\r
+ alOut(m + alScale,inst->mScale);\r
+ alOut(m + alAttack,inst->mAttack);\r
+ alOut(m + alSus,inst->mSus);\r
+ alOut(m + alWave,inst->mWave);\r
+\r
+ // Most percussive instruments only use one cell\r
+ if (c != 0xff)\r
+ {\r
+ alOut(c + alChar,inst->cChar);\r
+ alOut(c + alScale,inst->cScale);\r
+ alOut(c + alAttack,inst->cAttack);\r
+ alOut(c + alSus,inst->cSus);\r
+ alOut(c + alWave,inst->cWave);\r
+ }\r
+\r
+ alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right\r
+}\r
+//#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ALStopSound() - Turns off any sound effects playing through the\r
+// AdLib card\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_ALStopSound(void)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ /*(long)*/alSound = 0;\r
+ alOut(alFreqH + 0,0);\r
+\r
+asm popf\r
+}\r
+\r
+static void\r
+SDL_AlSetFXInst(Instrument far *inst)\r
+{\r
+ byte c,m;\r
+\r
+ m = modifiers[0];\r
+ c = carriers[0];\r
+ alOut(m + alChar,inst->mChar);\r
+ alOut(m + alScale,inst->mScale);\r
+ alOut(m + alAttack,inst->mAttack);\r
+ alOut(m + alSus,inst->mSus);\r
+ alOut(m + alWave,inst->mWave);\r
+ alOut(c + alChar,inst->cChar);\r
+ alOut(c + alScale,inst->cScale);\r
+ alOut(c + alAttack,inst->cAttack);\r
+ alOut(c + alSus,inst->cSus);\r
+ alOut(c + alWave,inst->cWave);\r