VGMSNDOBJ = vgmSnd.$(OBJ)
OLDLIBOBJS=bitmap.$(OBJ) 16render.$(OBJ)
GFXLIBOBJS = 16_vl.$(OBJ) 16_vl_1.$(OBJ) 16_vl_2.$(OBJ) 16_vlpal.$(OBJ) 16text.$(OBJ) scroll16.$(OBJ) 16_spri.$(OBJ)
-16LIBOBJS = 16_mm.$(OBJ) 16_pm.$(OBJ) 16_ca.$(OBJ) 16_tail.$(OBJ) 16_head.$(OBJ) 16_enti.$(OBJ) 16_dbg.$(OBJ) 16_in.$(OBJ) kitten.$(OBJ) 16_hc.$(OBJ) 16_wcpu.$(OBJ) 16_timer.$(OBJ) jsmn.$(OBJ) 16_map.$(OBJ) 16_sd.$(OBJ) 16_tail_.$(OBJ) 16_dbg_1.$(OBJ)
+16LIBOBJS = 16_mm.$(OBJ) 16_pm.$(OBJ) 16_ca.$(OBJ) 16_tail.$(OBJ) 16_head.$(OBJ) 16_enti.$(OBJ) 16_dbg.$(OBJ) 16_in.$(OBJ) kitten.$(OBJ) 16_hc.$(OBJ) 16_wcpu.$(OBJ) 16_timer.$(OBJ) jsmn.$(OBJ) 16_map.$(OBJ) 16_sd.$(OBJ) 16_snd.$(OBJ) 16_tail_.$(OBJ) 16_dbg_1.$(OBJ)
DOSLIBOBJ = adlib.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) dos.$(OBJ) cpu.$(OBJ)
!ifeq DEBUGSERIAL 1
DOSLIBOBJ += 8250.$(OBJ)
exmmtest.exe &
vgmtest.exe &
sountest.exe &
+ imfplay.exe &
+ sdtest.exe &
xcroll.exe &
0croll.exe &
1croll.exe &
tesuto.exe &
0tesuto.exe &
maptest.exe &
- imfplay.exe &
vrldbg.exe
#zcroll.exe &
TESTEXEC2 = &
$(TESTEXEC2) &
$(TESTEXEC3)
-all: $(EXEC) id_sd.$(OBJ)
+all: $(EXEC)
testexec: $(EXEC) $(TESTEXEC2)
#
inputest.exe: inputest.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib
sountest.exe: sountest.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib
imfplay.exe: imfplay.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib
+sdtest.exe: sdtest.$(OBJ) $(16LIB) $(DOSLIB) gfx.lib
vrldbg.exe: vrldbg.$(OBJ) #gfx.lib $(DOSLIB)
pcxtest.exe: pcxtest.$(OBJ) gfx.lib $(DOSLIB) $(16LIB)
vrstest.exe: vrstest.$(OBJ) $(16LIB) gfx.lib $(DOSLIB)
fontgfx.$(OBJ):$(SRC)/fontgfx.c
inputest.$(OBJ):$(SRC)/inputest.c
#inntest.$(OBJ):$(SRC)/inntest.c
-sountest.$(OBJ): $(SRC)/sountest.c
+sountest.$(OBJ): $(SRC)/sountest.c
+sdtest.$(OBJ): $(SRC)/sdtest.c
imfplay.$(OBJ): $(SRC)/imfplay.c
vrldbg.$(OBJ): $(SRC)/vrldbg.c
#miditest.$(OBJ): $(SRC)/miditest.c
16_tail.$(OBJ): $(SRCLIB)/16_tail.c $(SRCLIB)/16_tail.h
16_tail_.$(OBJ): $(SRCLIB)/16_tail_.c $(SRCLIB)/16_tail.h
16_hc.$(OBJ): $(SRCLIB)/16_hc.c $(SRCLIB)/16_hc.h
+16_snd.$(OBJ): $(SRCLIB)/16_snd.c $(SRCLIB)/16_snd.h
16_sd.$(OBJ): $(SRCLIB)/16_sd.c $(SRCLIB)/16_sd.h
-id_sd.$(OBJ): $(SRCLIB)/id_sd.c $(SRCLIB)/id_sd.h
jsmn.$(OBJ): $(JSMNLIB)/jsmn.c $(JSMNLIB)/jsmn.h
kitten.$(OBJ): $(NYANLIB)/kitten.c $(NYANLIB)/kitten.h
vgmSnd.$(OBJ): $(VGMSNDLIB)/vgmSnd.c $(VGMSNDLIB)/vgmSnd.h
#include "src/lib/16_mm.h"
#include "src/lib/16_hc.h"
#include "src/lib/16_dbg.h"
-#include "src/lib/16_sd.h"
+#include "src/lib/16_snd.h"
extern struct glob_game_vars *ggvv;
*\r
*/\r
\r
+//\r
+// ID Engine\r
+// ID_SD.c - Sound Manager for Wolfenstein 3D\r
+// v1.2w\r
+// By Jason Blochowiak\r
+// Open Watcom port by sparky4\r
+//\r
+\r
+//\r
+// This module handles dealing with generating sound on the appropriate\r
+// hardware\r
+//\r
+// Depends on: User Mgr (for parm checking)\r
+//\r
+// Globals:\r
+// For User Mgr:\r
+// SoundSourcePresent - Sound Source thingie present?\r
+// SoundBlasterPresent - SoundBlaster card present?\r
+// AdLibPresent - AdLib card present?\r
+// SoundMode - What device is used for sound effects\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
+//\r
+\r
+#pragma hdrstop // Wierdo thing with MUSE\r
+\r
+#include <dos.h>\r
+\r
+#ifndef _MUSE_ // Will be defined in ID_Types.h\r
#include "src/lib/16_sd.h"\r
+#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
+//#define SD_USECATA3DSETTIMERSPEED\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
-static void interrupt (*t0OldService)(void);\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
-void opl2out(word reg, word data)\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
- {\r
- mov ax,reg\r
- mov dx,word ptr [ADLIB_FM_ADDRESS]\r
- or ah,ah\r
- jz @@1\r
- add dx,2\r
-@@1: out dx,al\r
- mov cx,6\r
-@@2: in al,dx\r
- loop @@2\r
- inc dl\r
- mov ax,data\r
- out dx,al\r
- dec dl\r
- mov cx,36\r
-@@3: in al,dx\r
- loop @@3\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 opl3out(word reg, word data)\r
+void SDL_DoFX()\r
{\r
- __asm\r
+ if(pcSound)\r
{\r
- mov ax,reg\r
- mov dx,word ptr [ADLIB_FM_ADDRESS]\r
- or ah,ah\r
- jz @@1\r
- add dx,2\r
-@@1: out dx,al\r
- inc dl\r
- mov ax,data\r
- out dx,al\r
- dec dl\r
- mov cx,26\r
-@@2: in al,dx\r
- loop @@2\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 opl3exp(word data)\r
+void SDL_DoFast()\r
{\r
- __asm\r
+ count_fx++;\r
+ if(count_fx>=5)\r
{\r
- mov ax,data\r
- mov dx,word ptr [ADLIB_FM_ADDRESS]\r
- add dx,2\r
- out dx,al\r
- mov cx,6\r
-@@1: in al,dx\r
- loop @@1\r
- inc dl\r
- mov al,ah\r
- out dx,al\r
- mov cx,36\r
-@@2: in al,dx\r
- loop @@2\r
- }\r
-}\r
-\r
-/* Function: FMResest *******************************************************\r
-*\r
-* Description: quick and dirty sound card reset (zeros all\r
-* registers).\r
-*\r
-*/\r
-void FMReset(void/*int percusiveMode*/)\r
-{\r
- int i;\r
-\r
- /* zero all registers */\r
- for(i = MIN_REGISTER; i < MAX_REGISTER+1; i++) opl2out(i, 0);\r
-\r
- /* allow FM chips to control the waveform of each operator */\r
- opl2out(0x01, 0x20);\r
-\r
- /* set rhythm enabled (6 melodic voices, 5 percussive) */\r
- opl2out(0xBD, 0x20);\r
-\r
- //FMSetPercusiveMode(percusiveMode);\r
-} /* End of FMReset */\r
-\r
-/* Function: FMKeyOff *******************************************************\r
-*\r
-* Parameters: voice - which voice to turn off.\r
-*\r
-* Description: turns off the specified voice.\r
-*\r
-*/\r
-void FMKeyOff(int voice)\r
-{\r
- int regNum;\r
-\r
- /* turn voice off */\r
- regNum = 0xB0 + voice % 11;//NUMVOICE;\r
- opl2out(regNum, 0x0E);\r
-} /* End of FMKeyOff */\r
-\r
-/* Function: FMKeyOn *******************************************************\r
-*\r
-* Parameters: voice - which voice to turn on.\r
-* freq - its frequency (note).\r
-* octave - its octave.\r
-*\r
-* Description: turns on a voice of specfied frequency and\r
-* octave.\r
-*\r
-*/\r
-void FMKeyOn(int voice, int freq, int octave)\r
-{\r
- int regNum, tmp;\r
-\r
- regNum = 0xA0 + voice % 11;//NUMVOICE;\r
- opl2out(regNum, freq & 0xff);\r
- regNum = 0xB0 + voice % 11;//NUMVOICE;\r
- tmp = (freq >> 8) | (octave << 2) | 0x20;\r
- opl2out(regNum, tmp);\r
-} /* End of FMKeyOn */\r
-\r
-/* Function: FMSetVoice *****************************************************\r
-*\r
-* Parameters: voiceNum - which voice to set.\r
-* ins - instrument to set voice.\r
-*\r
-* Description: sets the instrument of a voice.\r
-*\r
-*/\r
-void FMSetVoice(int voiceNum, FMInstrument *ins){\r
- int opCellNum, cellOffset;\r
-\r
- voiceNum %= 11;//NUMVOICE;\r
- cellOffset = voiceNum % 3 + ((voiceNum / 3) << 3);\r
-\r
- /* set sound characteristic */\r
- opCellNum = 0x20 + (char)cellOffset;\r
- opl2out(opCellNum, ins->SoundCharacteristic[0]);\r
- opCellNum += 3;\r
- opl2out(opCellNum, ins->SoundCharacteristic[1]);\r
-\r
- /* set level/output */\r
- opCellNum = 0x40 + (char)cellOffset;\r
- opl2out(opCellNum, ins->Level[0]);\r
- opCellNum += 3;\r
- opl2out(opCellNum, ins->Level[1]);\r
-\r
- /* set Attack/Decay */\r
- opCellNum = 0x60 + (char)cellOffset;\r
- opl2out(opCellNum, ins->AttackDecay[0]);\r
- opCellNum += 3;\r
- opl2out(opCellNum, ins->AttackDecay[1]);\r
-\r
- /* set Sustain/Release */\r
- opCellNum = 0x80 + (char)cellOffset;\r
- opl2out(opCellNum, ins->SustainRelease[0]);\r
- opCellNum += 3;\r
- opl2out(opCellNum, ins->SustainRelease[1]);\r
-\r
- /* set Wave Select */\r
- opCellNum = 0xE0 + (char)cellOffset;\r
- opl2out(opCellNum, ins->WaveSelect[0]);\r
- opCellNum += 3;\r
- opl2out(opCellNum, ins->WaveSelect[1]);\r
-\r
- /* set Feedback/Selectivity */\r
- opCellNum = (byte)0xC0 + (byte)voiceNum;\r
- opl2out(opCellNum, ins->Feedback);\r
-} /* End of FMSetVoice */\r
-\r
-\r
-//newer sd\r
-\r
-\r
-struct glob_game_vars *ggvv;\r
-// WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models\r
-void interrupt SDL_irq0()\r
-{\r
- ggvv->ca.sd.irq0_ticks++;\r
- if ((ggvv->ca.sd.irq0_cnt += ggvv->ca.sd.irq0_add) >= ggvv->ca.sd.irq0_max) {\r
- ggvv->ca.sd.irq0_cnt -= ggvv->ca.sd.irq0_max;\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
- p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);\r
+ else\r
+ {\r
+ outp(0x20,0x20);\r
}\r
}\r
\r
-void SD_Initimf(global_game_variables_t *gvar)\r
+// Timer 0 ISR for 700Hz interrupts\r
+void interrupt SDL_t0FastAsmService(void)\r
{\r
- if (!init_adlib()) {\r
- printf("Cannot init library\n");\r
- return;\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
- if (!probe_8254()) { /* we need the timer to keep time with the music */\r
- printf("8254 timer not found\n");\r
- return;\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
- gvar->ca.sd.imf_delay_countdown=0;\r
- gvar->ca.sd.imf_music=\r
- gvar->ca.sd.imf_play_ptr=\r
- gvar->ca.sd.imf_music_end=NULL;\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
- SD_adlib_shut_up();\r
- shutdown_adlib_opl3(); // NTS: Apparently the music won't play otherwise\r
+asm popf\r
+#else\r
+ TimerDivisor = 0x10000;\r
+#endif\r
}\r
\r
-void SD_imf_reset_music(global_game_variables_t *gvar)\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
- gvar->ca.sd.imf_music = gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music_end = NULL;\r
- gvar->ca.sd.imf_delay_countdown = 0;\r
+ TimerRate = ints;\r
+ SDL_SetTimer0(1192030 / ints);\r
}\r
\r
-void SD_StartupTimer(global_game_variables_t *gvar)\r
+#ifndef SD_USECATA3DSETTIMERSPEED\r
+static void\r
+SDL_SetTimerSpeed(void)\r
{\r
- gvar->ca.sd.irq0_ticks=\r
- gvar->ca.sd.irq0_cnt = 0;\r
- gvar->ca.sd.irq0_add = 182;\r
- gvar->ca.sd.irq0_max = 1000; /* about 18.2Hz */\r
- gvar->ca.sd.tickrate = 700;\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
- write_8254_system_timer(T8254_REF_CLOCK_HZ / gvar->ca.sd.tickrate);\r
- t0OldService = _dos_getvect(8); /*IRQ0*/\r
- _dos_setvect(8,SDL_irq0);\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
- _cli();\r
- gvar->ca.sd.irq0_ticks = gvar->ca.sd.ptick = 0;\r
- _sti();\r
+ if (MusicMode == smm_AdLib)\r
+ rate = TickBase * 8;\r
+ else\r
+ rate = TickBase * 2;\r
+ SDL_SetIntsPerSec(rate);\r
}\r
+#endif\r
\r
-void SD_ShutdownTimer()\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
- _dos_setvect(8,t0OldService);\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
-void SD_imf_free_music(global_game_variables_t *gvar)\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
-#ifndef SD_USESCAMMPM\r
- if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music);\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
- MM_FreePtr(MEMPTRCONV gvar->ca.audiosegs[0], gvar); //TODO make behave like id engine\r
+static void\r
#endif\r
- SD_imf_reset_music(gvar);\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
-int SD_imf_load_music(const char *path, global_game_variables_t *gvar)\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
- unsigned long len;\r
- unsigned char buf[8];\r
- int fd;\r
+asm pushf\r
+asm cli\r
\r
-#ifndef SD_USESCAMMPM\r
- SD_imf_free_music(gvar);\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
- SD_imf_reset_music(gvar);\r
+static void\r
#endif\r
+SDL_PCPlaySound(PCSound far *sound)\r
+{\r
+asm pushf\r
+asm cli\r
\r
- fd = open(path,O_RDONLY|O_BINARY);\r
- if (fd < 0) return 0;\r
+ pcLastSample = -1;\r
+ pcLengthLeft = sound->common.length;\r
+ pcSound = sound->data;\r
\r
- len = lseek(fd,0,SEEK_END);\r
- lseek(fd,0,SEEK_SET);\r
- read(fd,buf,2);\r
- if (buf[0] != 0 || buf[1] != 0) // type 1 IMF\r
- len = *((uint16_t*)buf);\r
- else\r
- lseek(fd,0,SEEK_SET);\r
+asm popf\r
+}\r
\r
- if (len == 0 || len > 65535UL) {\r
- close(fd);\r
- return 0;\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
- len -= len & 3;\r
+}\r
\r
-#ifndef SD_USESCAMMPM\r
- gvar->ca.sd.imf_music = malloc(len);\r
-#else\r
- MM_GetPtr(MEMPTRCONV gvar->ca.audiosegs[0],len, gvar);\r
- gvar->ca.sd.imf_music = (struct imf_entry *)gvar->ca.audiosegs[0];\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
- if (gvar->ca.sd.imf_music == NULL) {\r
- close(fd);\r
- return 0;\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
- read(fd,gvar->ca.sd.imf_music,len);\r
- close(fd);\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
- gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music;\r
- gvar->ca.sd.imf_music_end = gvar->ca.sd.imf_music + (len >> 2UL);\r
- return 1;\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 SD_imf_tick(global_game_variables_t *gvar)\r
+void\r
+SDL_DigitizedDone(void)\r
{\r
- if (gvar->ca.sd.imf_delay_countdown == 0) {\r
- do {\r
- adlib_write(gvar->ca.sd.imf_play_ptr->reg,gvar->ca.sd.imf_play_ptr->data);\r
- gvar->ca.sd.imf_delay_countdown = gvar->ca.sd.imf_play_ptr->delay;\r
- gvar->ca.sd.imf_play_ptr++;\r
- if (gvar->ca.sd.imf_play_ptr == gvar->ca.sd.imf_music_end)\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
-// printf("replay\n");\r
- gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music;\r
+ SDL_SoundFinished();\r
}\r
- } while (gvar->ca.sd.imf_delay_countdown == 0);\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
- else {\r
- gvar->ca.sd.imf_delay_countdown--;\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
-void SD_adlib_shut_up() {\r
- int i;\r
+// AdLib Code\r
\r
- memset(adlib_fm,0,sizeof(adlib_fm));\r
- memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));\r
- for (i=0;i < adlib_fm_voices;i++) {\r
- struct adlib_fm_operator *f;\r
- f = &adlib_fm[i].mod;\r
- f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
- f = &adlib_fm[i].car;\r
- f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\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
- for (i=0;i < adlib_fm_voices;i++) {\r
- struct adlib_fm_operator *f;\r
+ tracks[track - 1]->inst = *inst;\r
+ tracks[track - 1]->percussive = percussive;\r
\r
- f = &adlib_fm[i].mod;\r
- f->mod_multiple = 1;\r
- f->total_level = 63 - 16;\r
- f->attack_rate = 15;\r
- f->decay_rate = 4;\r
- f->sustain_level = 0;\r
- f->release_rate = 8;\r
- f->f_number = 400;\r
- f->sustain = 1;\r
- f->octave = 4;\r
- f->key_on = 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
\r
- f = &adlib_fm[i].car;\r
- f->mod_multiple = 1;\r
- f->total_level = 63 - 16;\r
- f->attack_rate = 15;\r
- f->decay_rate = 4;\r
- f->sustain_level = 0;\r
- f->release_rate = 8;\r
- f->f_number = 0;\r
- f->sustain = 1;\r
- f->octave = 0;\r
- f->key_on = 0;\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
- adlib_apply_all();\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
+\r
+ // Note: Switch commenting on these lines for old MUSE compatibility\r
+// alOut(alFeedCon,inst->nConn);\r
+ alOut(alFeedCon,0);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ALPlaySound() - Plays the specified sound on the AdLib card\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+#ifdef _MUSE_\r
+void\r
+#else\r
+static void\r
+#endif\r
+SDL_ALPlaySound(AdLibSound far *sound, global_game_variables_t *gvar)\r
+{\r
+ Instrument __far *inst;\r
+ byte huge *data;\r
+\r
+ SDL_ALStopSound();\r
+\r
+asm pushf\r
+asm cli\r
+\r
+ alLengthLeft = sound->common.length;\r
+ data = sound->data;\r
+ data++;\r
+ data--;\r
+ alSound = (byte far *)data;\r
+ alBlock = ((sound->block & 7) << 2) | 0x20;\r
+ inst = &sound->inst;\r
+\r
+ if (!(inst->mSus | inst->cSus))\r
+ {\r
+ asm popf\r
+ Quit(gvar, "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
+SDL_ALSoundService(void)\r
+{\r
+ byte s;\r
+\r
+ if (alSound)\r
+ {\r
+ s = *alSound++;\r
+ if (!s)\r
+ alOut(alFreqH + 0,0);\r
+ else\r
+ {\r
+ alOut(alFreqL + 0,s);\r
+ alOut(alFreqH + 0,alBlock);\r
+ }\r
+\r
+ if (!(--alLengthLeft))\r
+ {\r
+ /*(long)*/alSound = 0;\r
+ alOut(alFreqH + 0,0);\r
+ SDL_SoundFinished();\r
+ }\r
+ }\r
+}\r
+//#endif\r
+\r
+#if 0\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_SelectMeasure() - sets up sequencing variables for a given track\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SDL_SelectMeasure(ActiveTrack *track)\r
+{\r
+ track->seq = track->moods[track->mood];\r
+ track->nextevent = 0;\r
+}\r
+#endif\r
+\r
+//#if 0\r
+void\r
+SDL_ALService(void)\r
+{\r
+ byte a,v;\r
+ word w;\r
+\r
+ a=v=0;\r
+\r
+ if (!sqActive)\r
+ return;\r
+\r
+ while (sqHackLen && (sqHackTime <= alTimeCount))\r
+ {\r
+ w = *sqHackPtr++;\r
+ sqHackTime = alTimeCount + *sqHackPtr++;\r
+ asm mov dx,[w]\r
+ asm mov [a],dl\r
+ asm mov [v],dh\r
+ alOut(a,v);\r
+ sqHackLen -= 4;\r
+ }\r
+ alTimeCount++;\r
+ if (!sqHackLen)\r
+ {\r
+ sqHackPtr = (word far *)sqHack;\r
+ sqHackLen = sqHackSeqLen;\r
+ alTimeCount = sqHackTime = 0;\r
+ }\r
+}\r
+//#endif\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ShutAL() - Shuts down the AdLib card for sound effects\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_ShutAL(void)\r
+{\r
+asm pushf\r
+asm cli\r
+\r
+ alOut(alEffects,0);\r
+ alOut(alFreqH + 0,0);\r
+ SDL_AlSetFXInst(&alZeroInst);\r
+ alSound = 0;\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_CleanAL() - Totally shuts down the AdLib card\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_CleanAL(void)\r
+{\r
+ int i;\r
+\r
+asm pushf\r
+asm cli\r
+\r
+ alOut(alEffects,0);\r
+ for (i = 1;i < 0xf5;i++)\r
+ alOut(i,0);\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_StartAL() - Starts up the AdLib card for sound effects\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_StartAL(void)\r
+{\r
+ alFXReg = 0;\r
+ alOut(alEffects,alFXReg);\r
+ SDL_AlSetFXInst(&alZeroInst);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster\r
+// emulating an AdLib) present\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static boolean\r
+SDL_DetectAdLib(void)\r
+{\r
+ byte status1,status2;\r
+ int i;\r
+\r
+ alOut(4,0x60); // Reset T1 & T2\r
+ alOut(4,0x80); // Reset IRQ\r
+ status1 = readstat();\r
+ alOut(2,0xff); // Set timer 1\r
+ alOut(4,0x21); // Start timer 1\r
+ SDL_Delay(TimerDelay100);\r
+\r
+#if 0\r
+ __asm {\r
+ mov dx,0x388\r
+ mov cx,100\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+usecloop:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ in al,dx\r
+ loop usecloop\r
+ }\r
+#endif\r
+\r
+ status2 = readstat();\r
+ alOut(4,0x60);\r
+ alOut(4,0x80);\r
+\r
+ if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))\r
+ {\r
+ for (i = 1;i <= 0xf5;i++) // Zero all the registers\r
+ alOut(i,0);\r
+\r
+ alOut(1,0x20); // Set WSE=1\r
+ alOut(8,0); // Set CSM=0 & SEL=0\r
+\r
+ return(true);\r
+ }\r
+ else\r
+ return(false);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
+// dispatches to whatever other routines are appropriate\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+//static void interrupt\r
+void interrupt\r
+SDL_t0Service(void)\r
+{\r
+static word count = 1;\r
+ boolean myackflag = 0;\r
+\r
+//00#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,4 // red\r
+asm out dx,al\r
+//00#endif\r
+\r
+ HackCount++;\r
+\r
+ if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))\r
+ {\r
+ SDL_ALService();\r
+//SS SDL_SSService();\r
+// if (!(++count & 7))\r
+ if (!(++count % 10))\r
+ {\r
+ LocalTime++;\r
+ TimeCount++;\r
+ if (SoundUserHook)\r
+ SoundUserHook();\r
+ }\r
+// if (!(count & 3))\r
+ if (!(count % 5))\r
+ {\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ SDL_PCService();\r
+ break;\r
+ case sdm_AdLib:\r
+ SDL_ALSoundService();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (!(++count & 1))\r
+ {\r
+ LocalTime++;\r
+ TimeCount++;\r
+ if (SoundUserHook)\r
+ SoundUserHook();\r
+ }\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ SDL_PCService();\r
+ break;\r
+ case sdm_AdLib:\r
+ SDL_ALSoundService();\r
+ break;\r
+ }\r
+ }\r
+\r
+ __asm {\r
+ mov ax,[WORD PTR TimerCount]\r
+ add ax,[WORD PTR TimerDivisor]\r
+ mov [WORD PTR TimerCount],ax\r
+ jnc myack\r
+ jmp end1\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+myack:\r
+#ifdef __BORLANDC__\r
+ __asm {\r
+#endif\r
+ mov myackflag,1\r
+#ifdef __BORLANDC__\r
+ }\r
+#endif\r
+end1:\r
+#ifdef __WATCOMC__\r
+ }\r
+#endif\r
+ if(!myackflag)\r
+ t0OldService(); // If we overflow a word, time to call old int handler\r
+ else\r
+ outportb(0x20,0x20); // Ack the interrupt\r
+\r
+//00#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
+//00#endif\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_ShutDevice() - turns off whatever device was being used for sound fx\r
+//\r
+////////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_ShutDevice(void)\r
+{\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ SDL_ShutPC();\r
+ break;\r
+ case sdm_AdLib:\r
+ SDL_ShutAL();\r
+ break;\r
+ }\r
+ SoundMode = sdm_Off;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_CleanDevice() - totally shuts down all sound devices\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_CleanDevice(void)\r
+{\r
+ if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))\r
+ SDL_CleanAL();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SDL_StartDevice() - turns on whatever device is to be used for sound fx\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+static void\r
+SDL_StartDevice(void)\r
+{\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_AdLib:\r
+ SDL_StartAL();\r
+ break;\r
+ }\r
+ SoundNumber = SoundPriority = 0;\r
+}\r
+#if 0\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
+// Public routines\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_SetSoundMode() - Sets which sound hardware to use for sound effects\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+SD_SetSoundMode(SDMode mode, global_game_variables_t *gvar)\r
+{\r
+ boolean result = false;\r
+ word tableoffset;\r
+\r
+ SD_StopSound(gvar);\r
+\r
+#ifndef _MUSE_\r
+ if ((mode == sdm_AdLib) && !AdLibPresent)\r
+ mode = sdm_PC;\r
+\r
+ switch (mode)\r
+ {\r
+ case sdm_Off:\r
+ NeedsDigitized = false;\r
+ result = true;\r
+ break;\r
+ case sdm_PC:\r
+ tableoffset = STARTPCSOUNDS;\r
+ NeedsDigitized = false;\r
+ result = true;\r
+ break;\r
+ case sdm_AdLib:\r
+ if (AdLibPresent)\r
+ {\r
+ tableoffset = STARTADLIBSOUNDS;\r
+ NeedsDigitized = false;\r
+ result = true;\r
+ }\r
+ break;\r
+ }\r
+#else\r
+ result = true;\r
+#endif\r
+\r
+ if (result && (mode != SoundMode))\r
+ {\r
+ SDL_ShutDevice();\r
+ SoundMode = mode;\r
+#ifndef _MUSE_\r
+ SoundTable = (word *)(&gvar->ca.audiosegs[tableoffset]);\r
+#endif\r
+ SDL_StartDevice();\r
+ }\r
+\r
+ SDL_SetTimerSpeed();\r
+\r
+ return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_SetMusicMode() - sets the device to use for background music\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+SD_SetMusicMode(SMMode mode)\r
+{\r
+ boolean result = false;\r
+\r
+ SD_FadeOutMusic();\r
+ while (SD_MusicPlaying())\r
+ ;\r
+\r
+ switch (mode)\r
+ {\r
+ case smm_Off:\r
+ NeedsMusic = false;\r
+ result = true;\r
+ break;\r
+ case smm_AdLib:\r
+ if (AdLibPresent)\r
+ {\r
+ NeedsMusic = true;\r
+ result = true;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (result)\r
+ MusicMode = mode;\r
+\r
+ SDL_SetTimerSpeed();\r
+\r
+ return(result);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_Startup() - starts up the Sound Mgr\r
+// Detects all additional sound hardware and installs my ISR\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_Startup(global_game_variables_t *gvar)\r
+{\r
+ int i;\r
+\r
+ if (SD_Started)\r
+ return;\r
+#ifndef SD_USECATA3DSETTIMERSPEED\r
+ SDL_SetDS();\r
+#endif\r
+ ssIsTandy = false;\r
+//SS ssNoCheck = false;\r
+ alNoCheck = false;\r
+//SB sbNoCheck = false;\r
+//SB sbNoProCheck = false;\r
+#ifndef _MUSE_\r
+ for (i = 1;i < _argc;i++)\r
+ {\r
+ switch (US_CheckParm(_argv[i],ParmStrings))\r
+ {\r
+ case 0: // No AdLib detection\r
+ alNoCheck = true;\r
+ break;\r
+//SB case 1: // No SoundBlaster detection\r
+//SB sbNoCheck = true;\r
+//SB break;\r
+//SB case 2: // No SoundBlaster Pro detection\r
+//SB sbNoProCheck = true;\r
+//SB break;\r
+//SS case 3:\r
+//SS ssNoCheck = true; // No Sound Source detection\r
+//SS break;\r
+ case 4: // Tandy Sound Source handling\r
+ ssIsTandy = true;\r
+ break;\r
+//SS case 5: // Sound Source present at LPT1\r
+//SS ssPort = 1;\r
+//SS ssNoCheck = SoundSourcePresent = true;\r
+//SS break;\r
+//SS case 6: // Sound Source present at LPT2\r
+//SS ssPort = 2;\r
+//SS ssNoCheck = SoundSourcePresent = true;\r
+//SS break;\r
+//SS case 7: // Sound Source present at LPT3\r
+//SS ssPort = 3;\r
+//SS ssNoCheck = SoundSourcePresent = true;\r
+//SS break;\r
+ }\r
+ }\r
+#endif\r
+\r
+ SoundUserHook = 0;\r
+\r
+ t0OldService = getvect(8); // Get old timer 0 ISR\r
+#ifdef SD_USECATA3DSETTIMERSPEED\r
+ SDL_InitDelay(); // SDL_InitDelay() uses t0OldService\r
+\r
+ setvect(8,SDL_t0Service); // Set to my timer 0 ISR\r
+#endif\r
+ LocalTime = TimeCount = alTimeCount = 0;\r
+\r
+ SD_SetSoundMode(sdm_Off, gvar);\r
+ SD_SetMusicMode(smm_Off);\r
+\r
+//SS if (!ssNoCheck)\r
+//SS SoundSourcePresent = SDL_DetectSoundSource();\r
+\r
+ if (!alNoCheck)\r
+ {\r
+ AdLibPresent = SDL_DetectAdLib();\r
+//SB if (AdLibPresent) && !sbNoCheck)\r
+//SB {\r
+//SB int port = -1;\r
+//SB char *env = getenv("BLASTER");\r
+//SB if (env)\r
+//SB {\r
+//SB long temp;\r
+//SB while (*env)\r
+//SB {\r
+//SB while (isspace(*env))\r
+//SB env++;\r
+//SB\r
+//SB switch (toupper(*env))\r
+//SB {\r
+//SB case 'A':\r
+//SB temp = strtol(env + 1,&env,16);\r
+//SB if\r
+//SB (\r
+//SB (temp >= 0x210)\r
+//SB && (temp <= 0x260)\r
+//SB && (!(temp & 0x00f))\r
+//SB )\r
+//SB port = (temp - 0x200) >> 4;\r
+//SB else\r
+//SB Quit(gvar, "SD_Startup: Unsupported address value in BLASTER");\r
+//SB break;\r
+//SB case 'I':\r
+//SB temp = strtol(env + 1,&env,10);\r
+//SB if\r
+//SB (\r
+//SB (temp >= 0)\r
+//SB && (temp <= 10)\r
+//SB && (sbIntVectors[temp] != -1)\r
+//SB )\r
+//SB {\r
+//SB sbInterrupt = temp;\r
+//SB sbIntVec = sbIntVectors[sbInterrupt];\r
+//SB }\r
+//SB else\r
+//SB Quit(gvar, "SD_Startup: Unsupported interrupt value in BLASTER");\r
+//SB break;\r
+//SB case 'D':\r
+//SB temp = strtol(env + 1,&env,10);\r
+//SB if ((temp == 0) || (temp == 1) || (temp == 3))\r
+//SB SDL_SBSetDMA(temp);\r
+//SB else\r
+//SB Quit(gvar, "SD_Startup: Unsupported DMA value in BLASTER");\r
+//SB break;\r
+//SB default:\r
+//SB while (isspace(*env))\r
+//SB env++;\r
+//SB while (*env && !isspace(*env))\r
+//SB env++;\r
+//SB break;\r
+//SB }\r
+//SB }\r
+//SB }\r
+//SB SoundBlasterPresent = SDL_DetectSoundBlaster(port);\r
+//SB }\r
+ }\r
+\r
+ for (i = 0;i < 255;i++)\r
+ pcSoundLookup[i] = i * 60;\r
+\r
+//SB if (SoundBlasterPresent)\r
+//SB SDL_StartSB();\r
+\r
+ SDL_SetupDigi(gvar);\r
+\r
+ SD_Started = true;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
+// the config file was present or not.\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar)\r
+{\r
+ boolean gotsd,gotsm;\r
+\r
+ gotsd = gotsm = gotit;\r
+\r
+ if (gotsd) // Make sure requested sound hardware is available\r
+ {\r
+ switch (sd)\r
+ {\r
+ case sdm_AdLib:\r
+ gotsd = AdLibPresent;\r
+ break;\r
+ }\r
+ }\r
+ if (!gotsd)\r
+ {\r
+ if (AdLibPresent)\r
+ sd = sdm_AdLib;\r
+ else\r
+ sd = sdm_PC;\r
+ }\r
+ if (sd != SoundMode)\r
+ SD_SetSoundMode(sd, gvar);\r
+\r
+\r
+ if (gotsm) // Make sure requested music hardware is available\r
+ {\r
+ switch (sm)\r
+ {\r
+ case sdm_AdLib:\r
+ gotsm = AdLibPresent;\r
+ break;\r
+ }\r
+ }\r
+ if (!gotsm)\r
+ {\r
+ if (AdLibPresent)\r
+ sm = smm_AdLib;\r
+ }\r
+ if (sm != MusicMode)\r
+ SD_SetMusicMode(sm);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_Shutdown() - shuts down the Sound Mgr\r
+// Removes sound ISR and turns off whatever sound hardware was active\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_Shutdown(global_game_variables_t *gvar)\r
+{\r
+ if (!SD_Started)\r
+ return;\r
+\r
+ SD_MusicOff();\r
+ SD_StopSound(gvar);\r
+ SDL_ShutDevice();\r
+ SDL_CleanDevice();\r
+\r
+//SB if (SoundBlasterPresent)\r
+//SB SDL_ShutSB();\r
+\r
+//SS if (SoundSourcePresent)\r
+//SS SDL_ShutSS();\r
+\r
+ asm pushf\r
+ asm cli\r
+\r
+ SDL_SetTimer0(0);\r
+\r
+ setvect(8,t0OldService);\r
+\r
+ asm popf\r
+\r
+ SD_Started = false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
+// of a second from its timer 0 ISR\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_SetUserHook(void (* hook)(void))\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
+SD_PlaySound(soundnames sound, global_game_variables_t *gvar)\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
+\r
+ s = MK_FP(SoundTable[sound],0);\r
+ if ((SoundMode != sdm_Off) && !s)\r
+ Quit(gvar, "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, gvar);\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(gvar, "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, gvar);\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(gvar, "SD_PlaySound() - Zero length sound");\r
+ if (s->priority < SoundPriority)\r
+ return(false);\r
+\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ SDL_PCPlaySound((void far *)s);\r
+ break;\r
+ case sdm_AdLib:\r
+ SDL_ALPlaySound((void far *)s, gvar);\r
+ break;\r
+ }\r
+\r
+ SoundNumber = sound;\r
+ SoundPriority = s->priority;\r
+\r
+ return(false);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
+// no sound is playing\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+word\r
+SD_SoundPlaying(void)\r
+{\r
+ boolean result = false;\r
+\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ result = pcSound? true : false;\r
+ break;\r
+ case sdm_AdLib:\r
+ result = alSound? true : false;\r
+ break;\r
+ }\r
+\r
+ if (result)\r
+ return(SoundNumber);\r
+ else\r
+ return(false);\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_StopSound() - if a sound is playing, stops it\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_StopSound(global_game_variables_t *gvar)\r
+{\r
+ if (DigiPlaying)\r
+ SD_StopDigitized(gvar);\r
+\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ SDL_PCStopSound();\r
+ break;\r
+ case sdm_AdLib:\r
+ SDL_ALStopSound();\r
+ break;\r
+ }\r
+\r
+ SoundPositioned = false;\r
+\r
+ SDL_SoundFinished();\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_WaitSoundDone() - waits until the current sound is done playing\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_WaitSoundDone(void)\r
+{\r
+ while (SD_SoundPlaying())\r
+ ;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_MusicOn() - turns on the sequencer\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_MusicOn(void)\r
+{\r
+ sqActive = true;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_MusicOff() - turns off the sequencer and any playing notes\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_MusicOff(void)\r
+{\r
+ word i;\r
+\r
+\r
+ switch (MusicMode)\r
+ {\r
+ case smm_AdLib:\r
+ alFXReg = 0;\r
+ alOut(alEffects,0);\r
+ for (i = 0;i < sqMaxTracks;i++)\r
+ alOut(alFreqH + i + 1,0);\r
+ break;\r
+ }\r
+ sqActive = false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_StartMusic() - starts playing the music pointed to\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_StartMusic(MusicGroup far *music)\r
+{\r
+ SD_MusicOff();\r
+asm pushf\r
+asm cli\r
+\r
+ if (MusicMode == smm_AdLib)\r
+ {\r
+ sqHackPtr = sqHack = music->values;\r
+ sqHackSeqLen = sqHackLen = music->length;\r
+ sqHackTime = 0;\r
+ alTimeCount = 0;\r
+ SD_MusicOn();\r
+ }\r
+\r
+asm popf\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
+// to see if the fadeout is complete\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+void\r
+SD_FadeOutMusic(void)\r
+{\r
+ switch (MusicMode)\r
+ {\r
+ case smm_AdLib:\r
+ // DEBUG - quick hack to turn the music off\r
+ SD_MusicOff();\r
+ break;\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// SD_MusicPlaying() - returns true if music is currently playing, false if\r
+// not\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+boolean\r
+SD_MusicPlaying(void)\r
+{\r
+ boolean result;\r
+\r
+ switch (MusicMode)\r
+ {\r
+ case smm_AdLib:\r
+ result = false;\r
+ // DEBUG - not written\r
+ break;\r
+ default:\r
+ result = false;\r
+ }\r
+\r
+ return(result);\r
+}\r
+\r
+//#if 0\r
+//\r
+// SD ASS!\r
+//\r
+\r
+//variables for these assembly functions\r
+volatile boolean pcindicate;\r
+volatile unsigned/*boolean*/ MyDS;\r
+\r
+void SDL_SetDS()\r
+{\r
+ __asm {\r
+ mov ax,ds\r
+ mov [cs:MyDS],ds\r
+ ret\r
+ }\r
+}\r
+\r
+//\r
+\r
+// Timer 0 ISR for 7000Hz interrupts\r
+void interrupt SDL_t0ExtremeAsmService(void)\r
+{\r
+ if(pcindicate)\r
+ {\r
+ if(pcSound)\r
+ {\r
+ SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
+ pcLengthLeft--;\r
+ if(!pcLengthLeft)\r
+ {\r
+ pcSound=0;\r
+ SDL_turnOffPCSpeaker();\r
+ SDL_DigitizedDoneInIRQ();\r
+ }\r
+ }\r
+ }\r
+ extreme++;\r
+ if(extreme>=10)\r
+ {\r
+ extreme=0;\r
+ SDL_DoFast();\r
+ }\r
+ else\r
+ outp(0x20,0x20);\r
+}\r
+\r
+//\r
+\r
+void SDL_IndicatePC(boolean ind)\r
+{\r
+ pcindicate=ind;\r
+}\r
+\r
+void\r
+SDL_DigitizedDoneInIRQ(void)\r
+{\r
+ if (DigiNextAddr)\r
+ {\r
+ SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen/*,true*/);\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
+ {\r
+ DigiNumber = (soundnames) 0;\r
+ DigiPriority = 0;\r
+ }\r
+ SoundPositioned = false;\r
+ }\r
+ else\r
+ DigiMissed = true;\r
+ }\r
+}\r
+\r
+#if 0\r
+// Inside an interrupt handler interrupts should already be disabled\r
+// so don't disable them again and cause V86 exceptions which cost\r
+// aprox. 300 processor tics!\r
+\r
+//static\r
+void alOutInIRQ(byte n,byte b)\r
+{\r
+ __asm {\r
+ mov dx,0x388\r
+ mov al,[n]\r
+ out dx,al\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ inc dx\r
+ mov al,[b]\r
+ out dx,al\r
+\r
+ dec dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ in al,dx\r
+ }\r
+}\r
+#endif\r
*\r
*/\r
\r
-#ifndef __16_SD_H_\r
-#define __16_SD_H_\r
+//\r
+// ID Engine\r
+// ID_SD.h - Sound Manager Header\r
+// Version for Wolfenstein\r
+// By Jason Blochowiak\r
+// Open Watcom port by sparky4\r
+//\r
+\r
+#ifndef __16_SD__\r
+#define __16_SD__\r
\r
#include "src/lib/16_head.h"\r
-#include "src/lib/16_tail.h"\r
-#include <hw/8254/8254.h> /* 8254 timer */\r
-#include <hw/adlib/adlib.h>\r
-#include <hw/vga/vga.h>\r
-#include <hw/dos/dos.h>\r
-#include <hw/8259/8259.h>\r
-\r
-#define SD_USESCAMMPM\r
-\r
-#define MIN_REGISTER 0x01\r
-#define MAX_REGISTER 0xF5\r
-#define ADLIB_FM_ADDRESS 0x388 /* adlib address/status register */\r
-#define ADLIB_FM_DATA 0x389 /* adlib data register */\r
-\r
-/*\r
-* FM Instrument definition for .SBI files - SoundBlaster instrument\r
-* - these are the important parts - we will skip the header, but since\r
-* I am not sure where it starts and ends so I have had to guess.\r
-* However it SEEMS! to work. Each array has two values, one for\r
-* each operator.\r
-*/\r
-typedef struct{\r
- byte SoundCharacteristic[2]; /* modulator frequency multiple... */\r
- byte Level[2]; /* modulator frequency level... */\r
- byte AttackDecay[2]; /* modulator attack/decay... */\r
- byte SustainRelease[2]; /* modulator sustain/release... */\r
- byte WaveSelect[2]; /* output waveform distortion */\r
- byte Feedback; /* feedback algorithm and strength */\r
-} FMInstrument;\r
-\r
-void opl2out(word reg, word data);\r
-void opl3out(word reg, word data);\r
-void opl3exp(word data);\r
-\r
-void FMReset(void/*int percusiveMode*/);\r
-void FMKeyOff(int voice);\r
-void FMKeyOn(int voice, int freq, int octave);\r
-void FMSetVoice(int voiceNum, FMInstrument *ins);\r
-\r
-void SD_Initimf(global_game_variables_t *gvar);\r
-void SD_imf_reset_music(global_game_variables_t *gvar);\r
-void SD_StartupTimer(global_game_variables_t *gvar),\r
- SD_ShutdownTimer();\r
-void SD_imf_free_music(global_game_variables_t *gvar);\r
-int SD_imf_load_music(const char *path, global_game_variables_t *gvar);\r
-void interrupt SD_irq0(void);\r
-void SD_imf_tick(global_game_variables_t *gvar);\r
-void SD_adlib_shut_up();\r
-\r
-#endif /*__16_SND_H_*/\r
+#include "src/lib/16_pm.h"\r
+\r
+void alOut(byte n,byte b);\r
+\r
+#ifdef __DEBUG__\r
+#define __DEBUG_SoundMgr__\r
+#endif\r
+\r
+#define TickBase 70 // 70Hz per tick - used as a base for timer 0\r
+\r
+typedef enum {\r
+ sdm_Off,\r
+ sdm_PC,sdm_AdLib,\r
+ } SDMode;\r
+typedef enum {\r
+ smm_Off,smm_AdLib\r
+ } SMMode;\r
+typedef enum {\r
+ sds_Off,sds_PC,sds_SoundSource,sds_SoundBlaster\r
+ } SDSMode;\r
+typedef struct\r
+ {\r
+ dword length;\r
+ word priority;\r
+ } SoundCommon;\r
+\r
+// PC Sound stuff\r
+#define pcTimer 0x42\r
+#define pcTAccess 0x43\r
+#define pcSpeaker 0x61\r
+\r
+#define pcSpkBits 3\r
+\r
+typedef struct\r
+ {\r
+ SoundCommon common;\r
+ byte data[1];\r
+ } PCSound;\r
+\r
+// Registers for the Sound Blaster card - needs to be offset by n0 (0x10,0x20,0x30,0x40,0x50,0x60)\r
+#define sbReset 0x206 // W\r
+#define sbFMStatus 0x208 // R\r
+#define sbFMAddr 0x208 // W\r
+#define sbFMData 0x209 // W\r
+#define sbReadData 0x20a // R\r
+#define sbWriteCmd 0x20c // W\r
+#define sbWriteData 0x20c // W\r
+#define sbWriteStat 0x20c // R\r
+#define sbDataAvail 0x20e // R\r
+\r
+// Registers for the Sound Blaster Pro card - needs to be offset by n0 (0x20 or 0x40)\r
+#define sbpLFMStatus 0x200 // R\r
+#define sbpLFMAddr 0x200 // W\r
+#define sbpLFMData 0x201 // W\r
+#define sbpRFMStatus 0x202 // R\r
+#define sbpRFMAddr 0x202 // W\r
+#define sbpRFMData 0x203 // W\r
+#define sbpMixerAddr 0x204 // W\r
+#define sbpMixerData 0x205 // RW\r
+#define sbpCDData 0x210 // R\r
+#define sbpCDCommand 0x210 // W\r
+#define sbpCDStatus 0x211 // R\r
+#define sbpCDReset 0x212 // W\r
+\r
+// SBPro Mixer addresses\r
+#define sbpmReset 0x00\r
+#define sbpmVoiceVol 0x04\r
+#define sbpmMicMix 0x0a\r
+#define sbpmFilterADC 0x0c\r
+#define sbpmControl 0x0e\r
+#define sbpmMasterVol 0x22\r
+#define sbpmFMVol 0x26\r
+#define sbpmCDVol 0x28\r
+#define sbpmLineVol 0x2e\r
+\r
+typedef struct\r
+ {\r
+ SoundCommon common;\r
+ word hertz;\r
+ byte bits,\r
+ reference,\r
+ data[1];\r
+ } SampledSound;\r
+\r
+// Registers for the AdLib card\r
+#define alFMStatus 0x388 // R\r
+#define alFMAddr 0x388 // W\r
+#define alFMData 0x389 // W\r
+\r
+// Register addresses\r
+// Operator stuff\r
+#define alChar 0x20\r
+#define alScale 0x40\r
+#define alAttack 0x60\r
+#define alSus 0x80\r
+#define alWave 0xe0\r
+// Channel stuff\r
+#define alFreqL 0xa0\r
+#define alFreqH 0xb0\r
+#define alFeedCon 0xc0\r
+// Global stuff\r
+#define alEffects 0xbd\r
+\r
+typedef struct\r
+ {\r
+ byte mChar,cChar,\r
+ mScale,cScale,\r
+ mAttack,cAttack,\r
+ mSus,cSus,\r
+ mWave,cWave,\r
+ nConn,\r
+\r
+ // These are only for Muse - these bytes are really unused\r
+ voice,\r
+ mode,\r
+ unused[3];\r
+ } Instrument;\r
+\r
+typedef struct\r
+ {\r
+ SoundCommon common;\r
+ Instrument inst;\r
+ byte block,\r
+ data[1];\r
+ } AdLibSound;\r
+\r
+//\r
+// Sequencing stuff\r
+//\r
+#define sqMaxTracks 10\r
+#define sqMaxMoods 1 // DEBUG\r
+\r
+#define sev_Null 0 // Does nothing\r
+#define sev_NoteOff 1 // Turns a note off\r
+#define sev_NoteOn 2 // Turns a note on\r
+#define sev_NotePitch 3 // Sets the pitch of a currently playing note\r
+#define sev_NewInst 4 // Installs a new instrument\r
+#define sev_NewPerc 5 // Installs a new percussive instrument\r
+#define sev_PercOn 6 // Turns a percussive note on\r
+#define sev_PercOff 7 // Turns a percussive note off\r
+#define sev_SeqEnd -1 // Terminates a sequence\r
+\r
+// Flags for MusicGroup.flags\r
+#define sf_Melodic 0\r
+#define sf_Percussive 1\r
+\r
+#if 1\r
+typedef struct\r
+ {\r
+ word length,\r
+ values[1];\r
+ } MusicGroup;\r
+#else\r
+typedef struct\r
+ {\r
+ word flags,\r
+ count,\r
+ offsets[1];\r
+ } MusicGroup;\r
+#endif\r
+\r
+typedef struct\r
+ {\r
+ /* This part needs to be set up by the user */\r
+ word mood,far *moods[sqMaxMoods];\r
+\r
+ /* The rest is set up by the code */\r
+ Instrument inst;\r
+ boolean percussive;\r
+ word far *seq;\r
+ dword nextevent;\r
+ } ActiveTrack;\r
+\r
+#define sqmode_Normal 0\r
+#define sqmode_FadeIn 1\r
+#define sqmode_FadeOut 2\r
+\r
+#define sqMaxFade 64 // DEBUG\r
+\r
+\r
+// Global variables\r
+extern boolean AdLibPresent,\r
+ SoundSourcePresent,\r
+ SoundBlasterPresent,\r
+ NeedsMusic, // For Caching Mgr\r
+ SoundPositioned;\r
+extern SDMode SoundMode;\r
+extern SDSMode DigiMode;\r
+extern SMMode MusicMode;\r
+extern boolean DigiPlaying;\r
+extern int DigiMap[];\r
+extern dword TimeCount; // Global time in ticks\r
+\r
+// Function prototypes\r
+extern void SD_Startup(global_game_variables_t *gvar),\r
+ SD_Shutdown(global_game_variables_t *gvar),\r
+ SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar),\r
+\r
+ SD_PositionSound(int leftvol,int rightvol);\r
+extern boolean SD_PlaySound(soundnames sound, global_game_variables_t *gvar);\r
+extern void SD_SetPosition(int leftvol,int rightvol, global_game_variables_t *gvar),\r
+ SD_StopSound(global_game_variables_t *gvar),\r
+ SD_WaitSoundDone(void),\r
+\r
+ SD_StartMusic(MusicGroup far *music),\r
+ SD_MusicOn(void),\r
+ SD_MusicOff(void),\r
+ SD_FadeOutMusic(void),\r
+\r
+ SD_SetUserHook(void (*hook)(void));\r
+extern boolean SD_MusicPlaying(void),\r
+ SD_SetSoundMode(SDMode mode, global_game_variables_t *gvar),\r
+ SD_SetMusicMode(SMMode mode);\r
+extern word SD_SoundPlaying(void);\r
+\r
+extern void SD_SetDigiDevice(SDSMode, global_game_variables_t *gvar),\r
+ SD_PlayDigitized(word which,int leftpos,int rightpos, global_game_variables_t *gvar),\r
+ SD_StopDigitized(global_game_variables_t *gvar),\r
+ SD_Poll(global_game_variables_t *gvar);\r
+\r
+#ifdef _MUSE_ // MUSE Goes directly to the lower level routines\r
+extern void SDL_PCPlaySound(PCSound far *sound, global_game_variables_t *gvar),\r
+ SDL_PCStopSound(void),\r
+ SDL_ALPlaySound(AdLibSound far *sound),\r
+ SDL_ALStopSound(void);\r
+#endif\r
+\r
+#endif\r
+\r
--- /dev/null
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 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 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 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\r
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/16_snd.h"\r
+\r
+static void interrupt (*t0OldService)(void);\r
+\r
+void opl2out(word reg, word data)\r
+{\r
+ __asm\r
+ {\r
+ mov ax,reg\r
+ mov dx,word ptr [ADLIB_FM_ADDRESS]\r
+ or ah,ah\r
+ jz @@1\r
+ add dx,2\r
+@@1: out dx,al\r
+ mov cx,6\r
+@@2: in al,dx\r
+ loop @@2\r
+ inc dl\r
+ mov ax,data\r
+ out dx,al\r
+ dec dl\r
+ mov cx,36\r
+@@3: in al,dx\r
+ loop @@3\r
+ }\r
+}\r
+\r
+void opl3out(word reg, word data)\r
+{\r
+ __asm\r
+ {\r
+ mov ax,reg\r
+ mov dx,word ptr [ADLIB_FM_ADDRESS]\r
+ or ah,ah\r
+ jz @@1\r
+ add dx,2\r
+@@1: out dx,al\r
+ inc dl\r
+ mov ax,data\r
+ out dx,al\r
+ dec dl\r
+ mov cx,26\r
+@@2: in al,dx\r
+ loop @@2\r
+ }\r
+}\r
+\r
+void opl3exp(word data)\r
+{\r
+ __asm\r
+ {\r
+ mov ax,data\r
+ mov dx,word ptr [ADLIB_FM_ADDRESS]\r
+ add dx,2\r
+ out dx,al\r
+ mov cx,6\r
+@@1: in al,dx\r
+ loop @@1\r
+ inc dl\r
+ mov al,ah\r
+ out dx,al\r
+ mov cx,36\r
+@@2: in al,dx\r
+ loop @@2\r
+ }\r
+}\r
+\r
+/* Function: FMResest *******************************************************\r
+*\r
+* Description: quick and dirty sound card reset (zeros all\r
+* registers).\r
+*\r
+*/\r
+void FMReset(void/*int percusiveMode*/)\r
+{\r
+ int i;\r
+\r
+ /* zero all registers */\r
+ for(i = MIN_REGISTER; i < MAX_REGISTER+1; i++) opl2out(i, 0);\r
+\r
+ /* allow FM chips to control the waveform of each operator */\r
+ opl2out(0x01, 0x20);\r
+\r
+ /* set rhythm enabled (6 melodic voices, 5 percussive) */\r
+ opl2out(0xBD, 0x20);\r
+\r
+ //FMSetPercusiveMode(percusiveMode);\r
+} /* End of FMReset */\r
+\r
+/* Function: FMKeyOff *******************************************************\r
+*\r
+* Parameters: voice - which voice to turn off.\r
+*\r
+* Description: turns off the specified voice.\r
+*\r
+*/\r
+void FMKeyOff(int voice)\r
+{\r
+ int regNum;\r
+\r
+ /* turn voice off */\r
+ regNum = 0xB0 + voice % 11;//NUMVOICE;\r
+ opl2out(regNum, 0x0E);\r
+} /* End of FMKeyOff */\r
+\r
+/* Function: FMKeyOn *******************************************************\r
+*\r
+* Parameters: voice - which voice to turn on.\r
+* freq - its frequency (note).\r
+* octave - its octave.\r
+*\r
+* Description: turns on a voice of specfied frequency and\r
+* octave.\r
+*\r
+*/\r
+void FMKeyOn(int voice, int freq, int octave)\r
+{\r
+ int regNum, tmp;\r
+\r
+ regNum = 0xA0 + voice % 11;//NUMVOICE;\r
+ opl2out(regNum, freq & 0xff);\r
+ regNum = 0xB0 + voice % 11;//NUMVOICE;\r
+ tmp = (freq >> 8) | (octave << 2) | 0x20;\r
+ opl2out(regNum, tmp);\r
+} /* End of FMKeyOn */\r
+\r
+/* Function: FMSetVoice *****************************************************\r
+*\r
+* Parameters: voiceNum - which voice to set.\r
+* ins - instrument to set voice.\r
+*\r
+* Description: sets the instrument of a voice.\r
+*\r
+*/\r
+void FMSetVoice(int voiceNum, FMInstrument *ins){\r
+ int opCellNum, cellOffset;\r
+\r
+ voiceNum %= 11;//NUMVOICE;\r
+ cellOffset = voiceNum % 3 + ((voiceNum / 3) << 3);\r
+\r
+ /* set sound characteristic */\r
+ opCellNum = 0x20 + (char)cellOffset;\r
+ opl2out(opCellNum, ins->SoundCharacteristic[0]);\r
+ opCellNum += 3;\r
+ opl2out(opCellNum, ins->SoundCharacteristic[1]);\r
+\r
+ /* set level/output */\r
+ opCellNum = 0x40 + (char)cellOffset;\r
+ opl2out(opCellNum, ins->Level[0]);\r
+ opCellNum += 3;\r
+ opl2out(opCellNum, ins->Level[1]);\r
+\r
+ /* set Attack/Decay */\r
+ opCellNum = 0x60 + (char)cellOffset;\r
+ opl2out(opCellNum, ins->AttackDecay[0]);\r
+ opCellNum += 3;\r
+ opl2out(opCellNum, ins->AttackDecay[1]);\r
+\r
+ /* set Sustain/Release */\r
+ opCellNum = 0x80 + (char)cellOffset;\r
+ opl2out(opCellNum, ins->SustainRelease[0]);\r
+ opCellNum += 3;\r
+ opl2out(opCellNum, ins->SustainRelease[1]);\r
+\r
+ /* set Wave Select */\r
+ opCellNum = 0xE0 + (char)cellOffset;\r
+ opl2out(opCellNum, ins->WaveSelect[0]);\r
+ opCellNum += 3;\r
+ opl2out(opCellNum, ins->WaveSelect[1]);\r
+\r
+ /* set Feedback/Selectivity */\r
+ opCellNum = (byte)0xC0 + (byte)voiceNum;\r
+ opl2out(opCellNum, ins->Feedback);\r
+} /* End of FMSetVoice */\r
+\r
+\r
+//newer sd\r
+\r
+\r
+struct glob_game_vars *ggvv;\r
+// WARNING: subroutine call in interrupt handler. make sure you compile with -zu flag for large/compact memory models\r
+void interrupt SDL_irq0()\r
+{\r
+ ggvv->ca.sd.irq0_ticks++;\r
+ if ((ggvv->ca.sd.irq0_cnt += ggvv->ca.sd.irq0_add) >= ggvv->ca.sd.irq0_max) {\r
+ ggvv->ca.sd.irq0_cnt -= ggvv->ca.sd.irq0_max;\r
+ t0OldService();\r
+ }\r
+ else {\r
+ p8259_OCW2(0,P8259_OCW2_NON_SPECIFIC_EOI);\r
+ }\r
+}\r
+\r
+void SD_Initimf(global_game_variables_t *gvar)\r
+{\r
+ if (!init_adlib()) {\r
+ printf("Cannot init library\n");\r
+ return;\r
+ }\r
+ if (!probe_8254()) { /* we need the timer to keep time with the music */\r
+ printf("8254 timer not found\n");\r
+ return;\r
+ }\r
+\r
+ gvar->ca.sd.imf_delay_countdown=0;\r
+ gvar->ca.sd.imf_music=\r
+ gvar->ca.sd.imf_play_ptr=\r
+ gvar->ca.sd.imf_music_end=NULL;\r
+\r
+ SD_adlib_shut_up();\r
+ shutdown_adlib_opl3(); // NTS: Apparently the music won't play otherwise\r
+}\r
+\r
+void SD_imf_reset_music(global_game_variables_t *gvar)\r
+{\r
+ gvar->ca.sd.imf_music = gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music_end = NULL;\r
+ gvar->ca.sd.imf_delay_countdown = 0;\r
+}\r
+\r
+void SD_StartupTimer(global_game_variables_t *gvar)\r
+{\r
+ gvar->ca.sd.irq0_ticks=\r
+ gvar->ca.sd.irq0_cnt = 0;\r
+ gvar->ca.sd.irq0_add = 182;\r
+ gvar->ca.sd.irq0_max = 1000; /* about 18.2Hz */\r
+ gvar->ca.sd.tickrate = 700;\r
+\r
+ write_8254_system_timer(T8254_REF_CLOCK_HZ / gvar->ca.sd.tickrate);\r
+ t0OldService = _dos_getvect(8); /*IRQ0*/\r
+ _dos_setvect(8,SDL_irq0);\r
+\r
+ _cli();\r
+ gvar->ca.sd.irq0_ticks = gvar->ca.sd.ptick = 0;\r
+ _sti();\r
+}\r
+\r
+void SD_ShutdownTimer()\r
+{\r
+ _dos_setvect(8,t0OldService);\r
+}\r
+\r
+void SD_imf_free_music(global_game_variables_t *gvar)\r
+{\r
+#ifndef SD_USESCAMMPM\r
+ if (gvar->ca.sd.imf_music) free(gvar->ca.sd.imf_music);\r
+#else\r
+ MM_FreePtr(MEMPTRCONV gvar->ca.audiosegs[0], gvar); //TODO make behave like id engine\r
+#endif\r
+ SD_imf_reset_music(gvar);\r
+}\r
+\r
+int SD_imf_load_music(const char *path, global_game_variables_t *gvar)\r
+{\r
+ unsigned long len;\r
+ unsigned char buf[8];\r
+ int fd;\r
+\r
+#ifndef SD_USESCAMMPM\r
+ SD_imf_free_music(gvar);\r
+#else\r
+ SD_imf_reset_music(gvar);\r
+#endif\r
+\r
+ fd = open(path,O_RDONLY|O_BINARY);\r
+ if (fd < 0) return 0;\r
+\r
+ len = lseek(fd,0,SEEK_END);\r
+ lseek(fd,0,SEEK_SET);\r
+ read(fd,buf,2);\r
+ if (buf[0] != 0 || buf[1] != 0) // type 1 IMF\r
+ len = *((uint16_t*)buf);\r
+ else\r
+ lseek(fd,0,SEEK_SET);\r
+\r
+ if (len == 0 || len > 65535UL) {\r
+ close(fd);\r
+ return 0;\r
+ }\r
+ len -= len & 3;\r
+\r
+#ifndef SD_USESCAMMPM\r
+ gvar->ca.sd.imf_music = malloc(len);\r
+#else\r
+ MM_GetPtr(MEMPTRCONV gvar->ca.audiosegs[0],len, gvar);\r
+ gvar->ca.sd.imf_music = (struct imf_entry *)gvar->ca.audiosegs[0];\r
+#endif\r
+ if (gvar->ca.sd.imf_music == NULL) {\r
+ close(fd);\r
+ return 0;\r
+ }\r
+ read(fd,gvar->ca.sd.imf_music,len);\r
+ close(fd);\r
+\r
+ gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music;\r
+ gvar->ca.sd.imf_music_end = gvar->ca.sd.imf_music + (len >> 2UL);\r
+ return 1;\r
+}\r
+\r
+void SD_imf_tick(global_game_variables_t *gvar)\r
+{\r
+ if (gvar->ca.sd.imf_delay_countdown == 0) {\r
+ do {\r
+ adlib_write(gvar->ca.sd.imf_play_ptr->reg,gvar->ca.sd.imf_play_ptr->data);\r
+ gvar->ca.sd.imf_delay_countdown = gvar->ca.sd.imf_play_ptr->delay;\r
+ gvar->ca.sd.imf_play_ptr++;\r
+ if (gvar->ca.sd.imf_play_ptr == gvar->ca.sd.imf_music_end)\r
+ {\r
+// printf("replay\n");\r
+ gvar->ca.sd.imf_play_ptr = gvar->ca.sd.imf_music;\r
+ }\r
+ } while (gvar->ca.sd.imf_delay_countdown == 0);\r
+ }\r
+ else {\r
+ gvar->ca.sd.imf_delay_countdown--;\r
+ }\r
+}\r
+\r
+void SD_adlib_shut_up() {\r
+ int i;\r
+\r
+ memset(adlib_fm,0,sizeof(adlib_fm));\r
+ memset(&adlib_reg_bd,0,sizeof(adlib_reg_bd));\r
+ for (i=0;i < adlib_fm_voices;i++) {\r
+ struct adlib_fm_operator *f;\r
+ f = &adlib_fm[i].mod;\r
+ f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+ f = &adlib_fm[i].car;\r
+ f->ch_a = f->ch_b = f->ch_c = f->ch_d = 1;\r
+ }\r
+\r
+ for (i=0;i < adlib_fm_voices;i++) {\r
+ struct adlib_fm_operator *f;\r
+\r
+ f = &adlib_fm[i].mod;\r
+ f->mod_multiple = 1;\r
+ f->total_level = 63 - 16;\r
+ f->attack_rate = 15;\r
+ f->decay_rate = 4;\r
+ f->sustain_level = 0;\r
+ f->release_rate = 8;\r
+ f->f_number = 400;\r
+ f->sustain = 1;\r
+ f->octave = 4;\r
+ f->key_on = 0;\r
+\r
+ f = &adlib_fm[i].car;\r
+ f->mod_multiple = 1;\r
+ f->total_level = 63 - 16;\r
+ f->attack_rate = 15;\r
+ f->decay_rate = 4;\r
+ f->sustain_level = 0;\r
+ f->release_rate = 8;\r
+ f->f_number = 0;\r
+ f->sustain = 1;\r
+ f->octave = 0;\r
+ f->key_on = 0;\r
+ }\r
+\r
+ adlib_apply_all();\r
+}\r
--- /dev/null
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 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 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 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\r
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#ifndef __16_SD_H_\r
+#define __16_SD_H_\r
+\r
+#include "src/lib/16_head.h"\r
+#include "src/lib/16_tail.h"\r
+#include <hw/8254/8254.h> /* 8254 timer */\r
+#include <hw/adlib/adlib.h>\r
+#include <hw/vga/vga.h>\r
+#include <hw/dos/dos.h>\r
+#include <hw/8259/8259.h>\r
+\r
+#define SD_USESCAMMPM\r
+\r
+#define MIN_REGISTER 0x01\r
+#define MAX_REGISTER 0xF5\r
+#define ADLIB_FM_ADDRESS 0x388 /* adlib address/status register */\r
+#define ADLIB_FM_DATA 0x389 /* adlib data register */\r
+\r
+/*\r
+* FM Instrument definition for .SBI files - SoundBlaster instrument\r
+* - these are the important parts - we will skip the header, but since\r
+* I am not sure where it starts and ends so I have had to guess.\r
+* However it SEEMS! to work. Each array has two values, one for\r
+* each operator.\r
+*/\r
+typedef struct{\r
+ byte SoundCharacteristic[2]; /* modulator frequency multiple... */\r
+ byte Level[2]; /* modulator frequency level... */\r
+ byte AttackDecay[2]; /* modulator attack/decay... */\r
+ byte SustainRelease[2]; /* modulator sustain/release... */\r
+ byte WaveSelect[2]; /* output waveform distortion */\r
+ byte Feedback; /* feedback algorithm and strength */\r
+} FMInstrument;\r
+\r
+void opl2out(word reg, word data);\r
+void opl3out(word reg, word data);\r
+void opl3exp(word data);\r
+\r
+void FMReset(void/*int percusiveMode*/);\r
+void FMKeyOff(int voice);\r
+void FMKeyOn(int voice, int freq, int octave);\r
+void FMSetVoice(int voiceNum, FMInstrument *ins);\r
+\r
+void SD_Initimf(global_game_variables_t *gvar);\r
+void SD_imf_reset_music(global_game_variables_t *gvar);\r
+void SD_StartupTimer(global_game_variables_t *gvar),\r
+ SD_ShutdownTimer();\r
+void SD_imf_free_music(global_game_variables_t *gvar);\r
+int SD_imf_load_music(const char *path, global_game_variables_t *gvar);\r
+void interrupt SD_irq0(void);\r
+void SD_imf_tick(global_game_variables_t *gvar);\r
+void SD_adlib_shut_up();\r
+\r
+#endif /*__16_SND_H_*/\r
+++ /dev/null
-/* Project 16 Source Code~\r
- * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
- *\r
- * This file is part of Project 16.\r
- *\r
- * Project 16 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 3 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * Project 16 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\r
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
- * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
- * Fifth Floor, Boston, MA 02110-1301 USA.\r
- *\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.c - Sound Manager for Wolfenstein 3D\r
-// v1.2w\r
-// By Jason Blochowiak\r
-// Open Watcom port by sparky4\r
-//\r
-\r
-//\r
-// This module handles dealing with generating sound on the appropriate\r
-// hardware\r
-//\r
-// Depends on: User Mgr (for parm checking)\r
-//\r
-// Globals:\r
-// For User Mgr:\r
-// SoundSourcePresent - Sound Source thingie present?\r
-// SoundBlasterPresent - SoundBlaster card present?\r
-// AdLibPresent - AdLib card present?\r
-// SoundMode - What device is used for sound effects\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
-//\r
-\r
-#pragma hdrstop // Wierdo thing with MUSE\r
-\r
-#include <dos.h>\r
-\r
-#ifndef _MUSE_ // Will be defined in ID_Types.h\r
-#include "src/lib/id_sd.h"\r
-#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
-//#define SD_USECATA3DSETTIMERSPEED\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
- switch (mode)\r
- {\r
- case sds_SoundBlaster:\r
- if (!SoundBlasterPresent)\r
- {\r
- if (SoundSourcePresent)\r
- mode = sds_SoundSource;\r
- else\r
- devicenotpresent = true;\r
- }\r
- break;\r
- case sds_SoundSource:\r
- if (!SoundSourcePresent)\r
- devicenotpresent = true;\r
- break;\r
- }\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
-\r
- // Note: Switch commenting on these lines for old MUSE compatibility\r
-// alOut(alFeedCon,inst->nConn);\r
- alOut(alFeedCon,0);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALPlaySound() - Plays the specified sound on the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_ALPlaySound(AdLibSound far *sound, global_game_variables_t *gvar)\r
-{\r
- Instrument __far *inst;\r
- byte huge *data;\r
-\r
- SDL_ALStopSound();\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alLengthLeft = sound->common.length;\r
- data = sound->data;\r
- data++;\r
- data--;\r
- alSound = (byte far *)data;\r
- alBlock = ((sound->block & 7) << 2) | 0x20;\r
- inst = &sound->inst;\r
-\r
- if (!(inst->mSus | inst->cSus))\r
- {\r
- asm popf\r
- Quit(gvar, "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
-SDL_ALSoundService(void)\r
-{\r
- byte s;\r
-\r
- if (alSound)\r
- {\r
- s = *alSound++;\r
- if (!s)\r
- alOut(alFreqH + 0,0);\r
- else\r
- {\r
- alOut(alFreqL + 0,s);\r
- alOut(alFreqH + 0,alBlock);\r
- }\r
-\r
- if (!(--alLengthLeft))\r
- {\r
- /*(long)*/alSound = 0;\r
- alOut(alFreqH + 0,0);\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-//#endif\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SelectMeasure() - sets up sequencing variables for a given track\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SDL_SelectMeasure(ActiveTrack *track)\r
-{\r
- track->seq = track->moods[track->mood];\r
- track->nextevent = 0;\r
-}\r
-#endif\r
-\r
-//#if 0\r
-void\r
-SDL_ALService(void)\r
-{\r
- byte a,v;\r
- word w;\r
-\r
- a=v=0;\r
-\r
- if (!sqActive)\r
- return;\r
-\r
- while (sqHackLen && (sqHackTime <= alTimeCount))\r
- {\r
- w = *sqHackPtr++;\r
- sqHackTime = alTimeCount + *sqHackPtr++;\r
- asm mov dx,[w]\r
- asm mov [a],dl\r
- asm mov [v],dh\r
- alOut(a,v);\r
- sqHackLen -= 4;\r
- }\r
- alTimeCount++;\r
- if (!sqHackLen)\r
- {\r
- sqHackPtr = (word far *)sqHack;\r
- sqHackLen = sqHackSeqLen;\r
- alTimeCount = sqHackTime = 0;\r
- }\r
-}\r
-//#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutAL() - Shuts down the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutAL(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- alOut(alFreqH + 0,0);\r
- SDL_AlSetFXInst(&alZeroInst);\r
- alSound = 0;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanAL() - Totally shuts down the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanAL(void)\r
-{\r
- int i;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- for (i = 1;i < 0xf5;i++)\r
- alOut(i,0);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartAL() - Starts up the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartAL(void)\r
-{\r
- alFXReg = 0;\r
- alOut(alEffects,alFXReg);\r
- SDL_AlSetFXInst(&alZeroInst);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster\r
-// emulating an AdLib) present\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_DetectAdLib(void)\r
-{\r
- byte status1,status2;\r
- int i;\r
-\r
- alOut(4,0x60); // Reset T1 & T2\r
- alOut(4,0x80); // Reset IRQ\r
- status1 = readstat();\r
- alOut(2,0xff); // Set timer 1\r
- alOut(4,0x21); // Start timer 1\r
- SDL_Delay(TimerDelay100);\r
-\r
-#if 0\r
- __asm {\r
- mov dx,0x388\r
- mov cx,100\r
-#ifdef __BORLANDC__\r
- }\r
-#endif\r
-usecloop:\r
-#ifdef __BORLANDC__\r
- __asm {\r
-#endif\r
- in al,dx\r
- loop usecloop\r
- }\r
-#endif\r
-\r
- status2 = readstat();\r
- alOut(4,0x60);\r
- alOut(4,0x80);\r
-\r
- if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))\r
- {\r
- for (i = 1;i <= 0xf5;i++) // Zero all the registers\r
- alOut(i,0);\r
-\r
- alOut(1,0x20); // Set WSE=1\r
- alOut(8,0); // Set CSM=0 & SEL=0\r
-\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
-// dispatches to whatever other routines are appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-//static void interrupt\r
-void interrupt\r
-SDL_t0Service(void)\r
-{\r
-static word count = 1;\r
- boolean myackflag = 0;\r
-\r
-//00#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,4 // red\r
-asm out dx,al\r
-//00#endif\r
-\r
- HackCount++;\r
-\r
- if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))\r
- {\r
- SDL_ALService();\r
-//SS SDL_SSService();\r
-// if (!(++count & 7))\r
- if (!(++count % 10))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
-// if (!(count & 3))\r
- if (!(count % 5))\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- if (!(++count & 1))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
-\r
- __asm {\r
- mov ax,[WORD PTR TimerCount]\r
- add ax,[WORD PTR TimerDivisor]\r
- mov [WORD PTR TimerCount],ax\r
- jnc myack\r
- jmp end1\r
-#ifdef __BORLANDC__\r
- }\r
-#endif\r
-myack:\r
-#ifdef __BORLANDC__\r
- __asm {\r
-#endif\r
- mov myackflag,1\r
-#ifdef __BORLANDC__\r
- }\r
-#endif\r
-end1:\r
-#ifdef __WATCOMC__\r
- }\r
-#endif\r
- if(!myackflag)\r
- t0OldService(); // If we overflow a word, time to call old int handler\r
- else\r
- outportb(0x20,0x20); // Ack the interrupt\r
-\r
-//00#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
-//00#endif\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutDevice() - turns off whatever device was being used for sound fx\r
-//\r
-////////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_ShutPC();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ShutAL();\r
- break;\r
- }\r
- SoundMode = sdm_Off;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanDevice() - totally shuts down all sound devices\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanDevice(void)\r
-{\r
- if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))\r
- SDL_CleanAL();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartDevice() - turns on whatever device is to be used for sound fx\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_AdLib:\r
- SDL_StartAL();\r
- break;\r
- }\r
- SoundNumber = SoundPriority = 0;\r
-}\r
-#if 0\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
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetSoundMode() - Sets which sound hardware to use for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetSoundMode(SDMode mode, global_game_variables_t *gvar)\r
-{\r
- boolean result = false;\r
- word tableoffset;\r
-\r
- SD_StopSound(gvar);\r
-\r
-#ifndef _MUSE_\r
- if ((mode == sdm_AdLib) && !AdLibPresent)\r
- mode = sdm_PC;\r
-\r
- switch (mode)\r
- {\r
- case sdm_Off:\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_PC:\r
- tableoffset = STARTPCSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- tableoffset = STARTADLIBSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- }\r
- break;\r
- }\r
-#else\r
- result = true;\r
-#endif\r
-\r
- if (result && (mode != SoundMode))\r
- {\r
- SDL_ShutDevice();\r
- SoundMode = mode;\r
-#ifndef _MUSE_\r
- SoundTable = (word *)(&gvar->ca.audiosegs[tableoffset]);\r
-#endif\r
- SDL_StartDevice();\r
- }\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetMusicMode() - sets the device to use for background music\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetMusicMode(SMMode mode)\r
-{\r
- boolean result = false;\r
-\r
- SD_FadeOutMusic();\r
- while (SD_MusicPlaying())\r
- ;\r
-\r
- switch (mode)\r
- {\r
- case smm_Off:\r
- NeedsMusic = false;\r
- result = true;\r
- break;\r
- case smm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- NeedsMusic = true;\r
- result = true;\r
- }\r
- break;\r
- }\r
-\r
- if (result)\r
- MusicMode = mode;\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Startup() - starts up the Sound Mgr\r
-// Detects all additional sound hardware and installs my ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Startup(global_game_variables_t *gvar)\r
-{\r
- int i;\r
-\r
- if (SD_Started)\r
- return;\r
-#ifndef SD_USECATA3DSETTIMERSPEED\r
- SDL_SetDS();\r
-#endif\r
- ssIsTandy = false;\r
-//SS ssNoCheck = false;\r
- alNoCheck = false;\r
-//SB sbNoCheck = false;\r
-//SB sbNoProCheck = false;\r
-#ifndef _MUSE_\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings))\r
- {\r
- case 0: // No AdLib detection\r
- alNoCheck = true;\r
- break;\r
-//SB case 1: // No SoundBlaster detection\r
-//SB sbNoCheck = true;\r
-//SB break;\r
-//SB case 2: // No SoundBlaster Pro detection\r
-//SB sbNoProCheck = true;\r
-//SB break;\r
-//SS case 3:\r
-//SS ssNoCheck = true; // No Sound Source detection\r
-//SS break;\r
- case 4: // Tandy Sound Source handling\r
- ssIsTandy = true;\r
- break;\r
-//SS case 5: // Sound Source present at LPT1\r
-//SS ssPort = 1;\r
-//SS ssNoCheck = SoundSourcePresent = true;\r
-//SS break;\r
-//SS case 6: // Sound Source present at LPT2\r
-//SS ssPort = 2;\r
-//SS ssNoCheck = SoundSourcePresent = true;\r
-//SS break;\r
-//SS case 7: // Sound Source present at LPT3\r
-//SS ssPort = 3;\r
-//SS ssNoCheck = SoundSourcePresent = true;\r
-//SS break;\r
- }\r
- }\r
-#endif\r
-\r
- SoundUserHook = 0;\r
-\r
- t0OldService = getvect(8); // Get old timer 0 ISR\r
-#ifdef SD_USECATA3DSETTIMERSPEED\r
- SDL_InitDelay(); // SDL_InitDelay() uses t0OldService\r
-\r
- setvect(8,SDL_t0Service); // Set to my timer 0 ISR\r
-#endif\r
- LocalTime = TimeCount = alTimeCount = 0;\r
-\r
- SD_SetSoundMode(sdm_Off, gvar);\r
- SD_SetMusicMode(smm_Off);\r
-\r
-//SS if (!ssNoCheck)\r
-//SS SoundSourcePresent = SDL_DetectSoundSource();\r
-\r
- if (!alNoCheck)\r
- {\r
- AdLibPresent = SDL_DetectAdLib();\r
-//SB if (AdLibPresent) && !sbNoCheck)\r
-//SB {\r
-//SB int port = -1;\r
-//SB char *env = getenv("BLASTER");\r
-//SB if (env)\r
-//SB {\r
-//SB long temp;\r
-//SB while (*env)\r
-//SB {\r
-//SB while (isspace(*env))\r
-//SB env++;\r
-//SB\r
-//SB switch (toupper(*env))\r
-//SB {\r
-//SB case 'A':\r
-//SB temp = strtol(env + 1,&env,16);\r
-//SB if\r
-//SB (\r
-//SB (temp >= 0x210)\r
-//SB && (temp <= 0x260)\r
-//SB && (!(temp & 0x00f))\r
-//SB )\r
-//SB port = (temp - 0x200) >> 4;\r
-//SB else\r
-//SB Quit(gvar, "SD_Startup: Unsupported address value in BLASTER");\r
-//SB break;\r
-//SB case 'I':\r
-//SB temp = strtol(env + 1,&env,10);\r
-//SB if\r
-//SB (\r
-//SB (temp >= 0)\r
-//SB && (temp <= 10)\r
-//SB && (sbIntVectors[temp] != -1)\r
-//SB )\r
-//SB {\r
-//SB sbInterrupt = temp;\r
-//SB sbIntVec = sbIntVectors[sbInterrupt];\r
-//SB }\r
-//SB else\r
-//SB Quit(gvar, "SD_Startup: Unsupported interrupt value in BLASTER");\r
-//SB break;\r
-//SB case 'D':\r
-//SB temp = strtol(env + 1,&env,10);\r
-//SB if ((temp == 0) || (temp == 1) || (temp == 3))\r
-//SB SDL_SBSetDMA(temp);\r
-//SB else\r
-//SB Quit(gvar, "SD_Startup: Unsupported DMA value in BLASTER");\r
-//SB break;\r
-//SB default:\r
-//SB while (isspace(*env))\r
-//SB env++;\r
-//SB while (*env && !isspace(*env))\r
-//SB env++;\r
-//SB break;\r
-//SB }\r
-//SB }\r
-//SB }\r
-//SB SoundBlasterPresent = SDL_DetectSoundBlaster(port);\r
-//SB }\r
- }\r
-\r
- for (i = 0;i < 255;i++)\r
- pcSoundLookup[i] = i * 60;\r
-\r
-//SB if (SoundBlasterPresent)\r
-//SB SDL_StartSB();\r
-\r
- SDL_SetupDigi(gvar);\r
-\r
- SD_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
-// the config file was present or not.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar)\r
-{\r
- boolean gotsd,gotsm;\r
-\r
- gotsd = gotsm = gotit;\r
-\r
- if (gotsd) // Make sure requested sound hardware is available\r
- {\r
- switch (sd)\r
- {\r
- case sdm_AdLib:\r
- gotsd = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsd)\r
- {\r
- if (AdLibPresent)\r
- sd = sdm_AdLib;\r
- else\r
- sd = sdm_PC;\r
- }\r
- if (sd != SoundMode)\r
- SD_SetSoundMode(sd, gvar);\r
-\r
-\r
- if (gotsm) // Make sure requested music hardware is available\r
- {\r
- switch (sm)\r
- {\r
- case sdm_AdLib:\r
- gotsm = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsm)\r
- {\r
- if (AdLibPresent)\r
- sm = smm_AdLib;\r
- }\r
- if (sm != MusicMode)\r
- SD_SetMusicMode(sm);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Shutdown() - shuts down the Sound Mgr\r
-// Removes sound ISR and turns off whatever sound hardware was active\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Shutdown(global_game_variables_t *gvar)\r
-{\r
- if (!SD_Started)\r
- return;\r
-\r
- SD_MusicOff();\r
- SD_StopSound(gvar);\r
- SDL_ShutDevice();\r
- SDL_CleanDevice();\r
-\r
-//SB if (SoundBlasterPresent)\r
-//SB SDL_ShutSB();\r
-\r
-//SS if (SoundSourcePresent)\r
-//SS SDL_ShutSS();\r
-\r
- asm pushf\r
- asm cli\r
-\r
- SDL_SetTimer0(0);\r
-\r
- setvect(8,t0OldService);\r
-\r
- asm popf\r
-\r
- SD_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
-// of a second from its timer 0 ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_SetUserHook(void (* hook)(void))\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
-SD_PlaySound(soundnames sound, global_game_variables_t *gvar)\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
-\r
- s = MK_FP(SoundTable[sound],0);\r
- if ((SoundMode != sdm_Off) && !s)\r
- Quit(gvar, "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, gvar);\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(gvar, "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, gvar);\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(gvar, "SD_PlaySound() - Zero length sound");\r
- if (s->priority < SoundPriority)\r
- return(false);\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCPlaySound((void far *)s);\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALPlaySound((void far *)s, gvar);\r
- break;\r
- }\r
-\r
- SoundNumber = sound;\r
- SoundPriority = s->priority;\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
-// no sound is playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-word\r
-SD_SoundPlaying(void)\r
-{\r
- boolean result = false;\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- result = pcSound? true : false;\r
- break;\r
- case sdm_AdLib:\r
- result = alSound? true : false;\r
- break;\r
- }\r
-\r
- if (result)\r
- return(SoundNumber);\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StopSound() - if a sound is playing, stops it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StopSound(global_game_variables_t *gvar)\r
-{\r
- if (DigiPlaying)\r
- SD_StopDigitized(gvar);\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCStopSound();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALStopSound();\r
- break;\r
- }\r
-\r
- SoundPositioned = false;\r
-\r
- SDL_SoundFinished();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_WaitSoundDone() - waits until the current sound is done playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_WaitSoundDone(void)\r
-{\r
- while (SD_SoundPlaying())\r
- ;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOn() - turns on the sequencer\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOn(void)\r
-{\r
- sqActive = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOff() - turns off the sequencer and any playing notes\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOff(void)\r
-{\r
- word i;\r
-\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- alFXReg = 0;\r
- alOut(alEffects,0);\r
- for (i = 0;i < sqMaxTracks;i++)\r
- alOut(alFreqH + i + 1,0);\r
- break;\r
- }\r
- sqActive = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StartMusic() - starts playing the music pointed to\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StartMusic(MusicGroup far *music)\r
-{\r
- SD_MusicOff();\r
-asm pushf\r
-asm cli\r
-\r
- if (MusicMode == smm_AdLib)\r
- {\r
- sqHackPtr = sqHack = music->values;\r
- sqHackSeqLen = sqHackLen = music->length;\r
- sqHackTime = 0;\r
- alTimeCount = 0;\r
- SD_MusicOn();\r
- }\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
-// to see if the fadeout is complete\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_FadeOutMusic(void)\r
-{\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- // DEBUG - quick hack to turn the music off\r
- SD_MusicOff();\r
- break;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicPlaying() - returns true if music is currently playing, false if\r
-// not\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_MusicPlaying(void)\r
-{\r
- boolean result;\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- result = false;\r
- // DEBUG - not written\r
- break;\r
- default:\r
- result = false;\r
- }\r
-\r
- return(result);\r
-}\r
-\r
-//#if 0\r
-//\r
-// SD ASS!\r
-//\r
-\r
-//variables for these assembly functions\r
-volatile boolean pcindicate;\r
-volatile unsigned/*boolean*/ MyDS;\r
-\r
-void SDL_SetDS()\r
-{\r
- __asm {\r
- mov ax,ds\r
- mov [cs:MyDS],ds\r
- ret\r
- }\r
-}\r
-\r
-//\r
-\r
-// Timer 0 ISR for 7000Hz interrupts\r
-void interrupt SDL_t0ExtremeAsmService(void)\r
-{\r
- if(pcindicate)\r
- {\r
- if(pcSound)\r
- {\r
- SDL_setPCSpeaker(((*pcSound++)&0x80)>>6);\r
- pcLengthLeft--;\r
- if(!pcLengthLeft)\r
- {\r
- pcSound=0;\r
- SDL_turnOffPCSpeaker();\r
- SDL_DigitizedDoneInIRQ();\r
- }\r
- }\r
- }\r
- extreme++;\r
- if(extreme>=10)\r
- {\r
- extreme=0;\r
- SDL_DoFast();\r
- }\r
- else\r
- outp(0x20,0x20);\r
-}\r
-\r
-//\r
-\r
-void SDL_IndicatePC(boolean ind)\r
-{\r
- pcindicate=ind;\r
-}\r
-\r
-void\r
-SDL_DigitizedDoneInIRQ(void)\r
-{\r
- if (DigiNextAddr)\r
- {\r
- SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen/*,true*/);\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
- {\r
- DigiNumber = (soundnames) 0;\r
- DigiPriority = 0;\r
- }\r
- SoundPositioned = false;\r
- }\r
- else\r
- DigiMissed = true;\r
- }\r
-}\r
-\r
-#if 0\r
-// Inside an interrupt handler interrupts should already be disabled\r
-// so don't disable them again and cause V86 exceptions which cost\r
-// aprox. 300 processor tics!\r
-\r
-//static\r
-void alOutInIRQ(byte n,byte b)\r
-{\r
- __asm {\r
- mov dx,0x388\r
- mov al,[n]\r
- out dx,al\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- inc dx\r
- mov al,[b]\r
- out dx,al\r
-\r
- dec dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
-\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
-\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
-\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- in al,dx\r
- }\r
-}\r
-#endif\r
+++ /dev/null
-/* Project 16 Source Code~\r
- * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
- *\r
- * This file is part of Project 16.\r
- *\r
- * Project 16 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 3 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * Project 16 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\r
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
- * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
- * Fifth Floor, Boston, MA 02110-1301 USA.\r
- *\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.h - Sound Manager Header\r
-// Version for Wolfenstein\r
-// By Jason Blochowiak\r
-// Open Watcom port by sparky4\r
-//\r
-\r
-#ifndef __16_SD__\r
-#define __16_SD__\r
-\r
-#include "src/lib/16_head.h"\r
-#include "src/lib/16_pm.h"\r
-\r
-void alOut(byte n,byte b);\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_SoundMgr__\r
-#endif\r
-\r
-#define TickBase 70 // 70Hz per tick - used as a base for timer 0\r
-\r
-typedef enum {\r
- sdm_Off,\r
- sdm_PC,sdm_AdLib,\r
- } SDMode;\r
-typedef enum {\r
- smm_Off,smm_AdLib\r
- } SMMode;\r
-typedef enum {\r
- sds_Off,sds_PC,sds_SoundSource,sds_SoundBlaster\r
- } SDSMode;\r
-typedef struct\r
- {\r
- dword length;\r
- word priority;\r
- } SoundCommon;\r
-\r
-// PC Sound stuff\r
-#define pcTimer 0x42\r
-#define pcTAccess 0x43\r
-#define pcSpeaker 0x61\r
-\r
-#define pcSpkBits 3\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- byte data[1];\r
- } PCSound;\r
-\r
-// Registers for the Sound Blaster card - needs to be offset by n0 (0x10,0x20,0x30,0x40,0x50,0x60)\r
-#define sbReset 0x206 // W\r
-#define sbFMStatus 0x208 // R\r
-#define sbFMAddr 0x208 // W\r
-#define sbFMData 0x209 // W\r
-#define sbReadData 0x20a // R\r
-#define sbWriteCmd 0x20c // W\r
-#define sbWriteData 0x20c // W\r
-#define sbWriteStat 0x20c // R\r
-#define sbDataAvail 0x20e // R\r
-\r
-// Registers for the Sound Blaster Pro card - needs to be offset by n0 (0x20 or 0x40)\r
-#define sbpLFMStatus 0x200 // R\r
-#define sbpLFMAddr 0x200 // W\r
-#define sbpLFMData 0x201 // W\r
-#define sbpRFMStatus 0x202 // R\r
-#define sbpRFMAddr 0x202 // W\r
-#define sbpRFMData 0x203 // W\r
-#define sbpMixerAddr 0x204 // W\r
-#define sbpMixerData 0x205 // RW\r
-#define sbpCDData 0x210 // R\r
-#define sbpCDCommand 0x210 // W\r
-#define sbpCDStatus 0x211 // R\r
-#define sbpCDReset 0x212 // W\r
-\r
-// SBPro Mixer addresses\r
-#define sbpmReset 0x00\r
-#define sbpmVoiceVol 0x04\r
-#define sbpmMicMix 0x0a\r
-#define sbpmFilterADC 0x0c\r
-#define sbpmControl 0x0e\r
-#define sbpmMasterVol 0x22\r
-#define sbpmFMVol 0x26\r
-#define sbpmCDVol 0x28\r
-#define sbpmLineVol 0x2e\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- word hertz;\r
- byte bits,\r
- reference,\r
- data[1];\r
- } SampledSound;\r
-\r
-// Registers for the AdLib card\r
-#define alFMStatus 0x388 // R\r
-#define alFMAddr 0x388 // W\r
-#define alFMData 0x389 // W\r
-\r
-// Register addresses\r
-// Operator stuff\r
-#define alChar 0x20\r
-#define alScale 0x40\r
-#define alAttack 0x60\r
-#define alSus 0x80\r
-#define alWave 0xe0\r
-// Channel stuff\r
-#define alFreqL 0xa0\r
-#define alFreqH 0xb0\r
-#define alFeedCon 0xc0\r
-// Global stuff\r
-#define alEffects 0xbd\r
-\r
-typedef struct\r
- {\r
- byte mChar,cChar,\r
- mScale,cScale,\r
- mAttack,cAttack,\r
- mSus,cSus,\r
- mWave,cWave,\r
- nConn,\r
-\r
- // These are only for Muse - these bytes are really unused\r
- voice,\r
- mode,\r
- unused[3];\r
- } Instrument;\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- Instrument inst;\r
- byte block,\r
- data[1];\r
- } AdLibSound;\r
-\r
-//\r
-// Sequencing stuff\r
-//\r
-#define sqMaxTracks 10\r
-#define sqMaxMoods 1 // DEBUG\r
-\r
-#define sev_Null 0 // Does nothing\r
-#define sev_NoteOff 1 // Turns a note off\r
-#define sev_NoteOn 2 // Turns a note on\r
-#define sev_NotePitch 3 // Sets the pitch of a currently playing note\r
-#define sev_NewInst 4 // Installs a new instrument\r
-#define sev_NewPerc 5 // Installs a new percussive instrument\r
-#define sev_PercOn 6 // Turns a percussive note on\r
-#define sev_PercOff 7 // Turns a percussive note off\r
-#define sev_SeqEnd -1 // Terminates a sequence\r
-\r
-// Flags for MusicGroup.flags\r
-#define sf_Melodic 0\r
-#define sf_Percussive 1\r
-\r
-#if 1\r
-typedef struct\r
- {\r
- word length,\r
- values[1];\r
- } MusicGroup;\r
-#else\r
-typedef struct\r
- {\r
- word flags,\r
- count,\r
- offsets[1];\r
- } MusicGroup;\r
-#endif\r
-\r
-typedef struct\r
- {\r
- /* This part needs to be set up by the user */\r
- word mood,far *moods[sqMaxMoods];\r
-\r
- /* The rest is set up by the code */\r
- Instrument inst;\r
- boolean percussive;\r
- word far *seq;\r
- dword nextevent;\r
- } ActiveTrack;\r
-\r
-#define sqmode_Normal 0\r
-#define sqmode_FadeIn 1\r
-#define sqmode_FadeOut 2\r
-\r
-#define sqMaxFade 64 // DEBUG\r
-\r
-\r
-// Global variables\r
-extern boolean AdLibPresent,\r
- SoundSourcePresent,\r
- SoundBlasterPresent,\r
- NeedsMusic, // For Caching Mgr\r
- SoundPositioned;\r
-extern SDMode SoundMode;\r
-extern SDSMode DigiMode;\r
-extern SMMode MusicMode;\r
-extern boolean DigiPlaying;\r
-extern int DigiMap[];\r
-extern dword TimeCount; // Global time in ticks\r
-\r
-// Function prototypes\r
-extern void SD_Startup(global_game_variables_t *gvar),\r
- SD_Shutdown(global_game_variables_t *gvar),\r
- SD_Default(boolean gotit,SDMode sd,SMMode sm, global_game_variables_t *gvar),\r
-\r
- SD_PositionSound(int leftvol,int rightvol);\r
-extern boolean SD_PlaySound(soundnames sound, global_game_variables_t *gvar);\r
-extern void SD_SetPosition(int leftvol,int rightvol, global_game_variables_t *gvar),\r
- SD_StopSound(global_game_variables_t *gvar),\r
- SD_WaitSoundDone(void),\r
-\r
- SD_StartMusic(MusicGroup far *music),\r
- SD_MusicOn(void),\r
- SD_MusicOff(void),\r
- SD_FadeOutMusic(void),\r
-\r
- SD_SetUserHook(void (*hook)(void));\r
-extern boolean SD_MusicPlaying(void),\r
- SD_SetSoundMode(SDMode mode, global_game_variables_t *gvar),\r
- SD_SetMusicMode(SMMode mode);\r
-extern word SD_SoundPlaying(void);\r
-\r
-extern void SD_SetDigiDevice(SDSMode, global_game_variables_t *gvar),\r
- SD_PlayDigitized(word which,int leftpos,int rightpos, global_game_variables_t *gvar),\r
- SD_StopDigitized(global_game_variables_t *gvar),\r
- SD_Poll(global_game_variables_t *gvar);\r
-\r
-#ifdef _MUSE_ // MUSE Goes directly to the lower level routines\r
-extern void SDL_PCPlaySound(PCSound far *sound, global_game_variables_t *gvar),\r
- SDL_PCStopSound(void),\r
- SDL_ALPlaySound(AdLibSound far *sound),\r
- SDL_ALStopSound(void);\r
-#endif\r
-\r
-#endif\r
-\r
--- /dev/null
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 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 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 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\r
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+\r
+#include "src/lib/16_sd.h"\r
+\r
+void main()\r
+{\r
+ /*static */global_game_variables_t gvar;\r
+ SD_Startup(&gvar);\r
+ SD_Shutdown(&gvar);\r
+}\r
#include <stdio.h>\r
\r
#include "src/lib/16_in.h"\r
-#include "src/lib/16_sd.h"\r
+#include "src/lib/16_snd.h"\r
//#include <hw/8254/8254.h> /* 8254 timer */\r
//#include <hw/adlib/adlib.h>\r
\r
*/\r
\r
#include "src/lib/vgmsnd/vgmSnd.h"\r
-#include "src/lib/16_sd.h"\r
+#include "src/lib/16_snd.h"\r
//#include "src/lib/doslib/adlib.h"\r
#include "src/lib/16_tail.h"\r
#include "src/lib/16_pm.h"\r