From: sparky4 Date: Mon, 11 Sep 2017 18:47:18 +0000 (-0500) Subject: 16_sd official port started. but class and work in the way X-Git-Url: http://4ch.mooo.com/gitweb/?a=commitdiff_plain;h=b932f865a55d4be5f9f814b9d884bbce6cbe55b4;p=16.git 16_sd official port started. but class and work in the way --- diff --git a/makefile b/makefile index d4cfb155..b0302b88 100755 --- a/makefile +++ b/makefile @@ -261,7 +261,7 @@ ALLEXEC = & $(TESTEXEC2) & $(TESTEXEC3) -all: $(EXEC) +all: $(EXEC)# id_sd.$(OBJ) testexec: $(EXEC) $(TESTEXEC2) # @@ -424,6 +424,7 @@ mapread.$(OBJ): $(SRCLIB)/mapread.c $(SRCLIB)/mapread.h 16_tail_.$(OBJ): $(SRCLIB)/16_tail_.c $(SRCLIB)/16_tail.h 16_hc.$(OBJ): $(SRCLIB)/16_hc.c $(SRCLIB)/16_hc.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 @@ -555,10 +556,16 @@ www: .symbolic @if exist 16.exe @wmake -s -h wwwdo @if exist 16.exe @wmake -s -h wwwext -wwwdo: .symbolic +cleanwww: .symbolic +wwwclean: .symbolic +wwwcl: .symbolic +clwww: .symbolic @for %f in (/var/www/$(EXEC)) do @if exist /var/www/%f $(REMOVECOMMAND) /var/www/%f @$(REMOVECOMMAND) /var/www/*.exe.zi* @$(REMOVECOMMAND) /var/www/*.zip.zi* + +wwwdo: .symbolic + @wmake clwww @for %f in ($(EXEC)) do @if exist %f @$(COPYCOMMAND) %f /var/www/ @./src/util/z.sh $(EXEC) $(EXEC) @./src/util/z2.sh data.zip data diff --git a/src/lib/16_tdef.h b/src/lib/16_tdef.h index 9b1bebd6..90222526 100755 --- a/src/lib/16_tdef.h +++ b/src/lib/16_tdef.h @@ -651,6 +651,49 @@ typedef struct //for 16_sd //========================================================================== + +///////////////////////////////////////////////// +// +// MUSE Header for .WL6 +// Created Tue Jul 14 15:04:53 1992 +// +///////////////////////////////////////////////// + +#define NUMSOUNDS 87 +//--#define NUMSNDCHUNKS 288 + +// +// Sound names & indexes +// +typedef enum { + HITWALLSND, // 0 + SELECTWPNSND, // 1 + SELECTITEMSND, // 2 + LASTSOUND + } soundnames; + +// +// Base offsets +// +#define STARTPCSOUNDS 0 +#define STARTADLIBSOUNDS 87 +#define STARTDIGISOUNDS 174 +#define STARTMUSIC 261 + +// +// Music names & indexes +// +typedef enum { + CORNER_MUS, // 0 + LASTMUSIC + } musicnames; + +///////////////////////////////////////////////// +// +// Thanks for playing with MUSE! +// +///////////////////////////////////////////////// + #pragma pack(push,1) typedef struct imf_entry { diff --git a/src/lib/doslib b/src/lib/doslib index 67de8406..59879510 160000 --- a/src/lib/doslib +++ b/src/lib/doslib @@ -1 +1 @@ -Subproject commit 67de840669443e3d3134ed12c1a0b3702d2b13cd +Subproject commit 59879510354f745c387353ec6f8d70ae6c6daac1 diff --git a/src/lib/id_sd.c b/src/lib/id_sd.c new file mode 100755 index 00000000..2a73fc69 --- /dev/null +++ b/src/lib/id_sd.c @@ -0,0 +1,2796 @@ +/* Project 16 Source Code~ + * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +// +// ID Engine +// ID_SD.c - Sound Manager for Wolfenstein 3D +// v1.2 +// By Jason Blochowiak +// + +// +// This module handles dealing with generating sound on the appropriate +// hardware +// +// Depends on: User Mgr (for parm checking) +// +// Globals: +// For User Mgr: +// SoundSourcePresent - Sound Source thingie present? +// SoundBlasterPresent - SoundBlaster card present? +// AdLibPresent - AdLib card present? +// SoundMode - What device is used for sound effects +// (Use SM_SetSoundMode() to set) +// MusicMode - What device is used for music +// (Use SM_SetMusicMode() to set) +// DigiMode - What device is used for digitized sound effects +// (Use SM_SetDigiDevice() to set) +// +// For Cache Mgr: +// NeedsDigitized - load digitized sounds? +// NeedsMusic - load music? +// + +#pragma hdrstop // Wierdo thing with MUSE + + + +//#ifdef _MUSE_ // Will be defined in ID_Types.h +#include "src/lib/id_sd.h" +//#else +//#include "ID_HEADS.H" +//#endif +#pragma hdrstop +#pragma warn -pia + +#ifdef nil +#undef nil +#endif +#define nil 0 + +#define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;} + +// Macros for SoundBlaster stuff +#define sbOut(n,b) outportb((n) + sbLocation,b) +#define sbIn(n) inportb((n) + sbLocation) +#define sbWriteDelay() while (sbIn(sbWriteStat) & 0x80); +#define sbReadDelay() while (sbIn(sbDataAvail) & 0x80); + +// Macros for AdLib stuff +#define selreg(n) outportb(alFMAddr,n) +#define writereg(n) outportb(alFMData,n) +#define readstat() inportb(alFMStatus) + +// Imports from ID_SD_A.ASM +/*extern*/ void SDL_SetDS(void), + SDL_IndicatePC(boolean on); +/*extern*/ void interrupt SDL_t0ExtremeAsmService(void), + SDL_t0FastAsmService(void), + SDL_t0SlowAsmService(void); + +// Global variables + boolean SoundSourcePresent, + AdLibPresent, + SoundBlasterPresent,SBProPresent, + NeedsDigitized,NeedsMusic, + SoundPositioned; + SDMode SoundMode; + SMMode MusicMode; + SDSMode DigiMode; + dword TimeCount; + word HackCount; + word *SoundTable; // Really * _seg *SoundTable, but that don't work + boolean ssIsTandy; + word ssPort = 2; + int DigiMap[LASTSOUND]; + +// Internal variables +static boolean SD_Started; + boolean nextsoundpos; + dword TimerDivisor,TimerCount; +static char *ParmStrings[] = + { + "noal", + "nosb", + "nopro", + "noss", + "sst", + "ss1", + "ss2", + "ss3", + nil + }; +static void (*SoundUserHook)(void); + soundnames SoundNumber,DigiNumber; + word SoundPriority,DigiPriority; + int LeftPosition,RightPosition; + void interrupt (*t0OldService)(void); + long LocalTime; + word TimerRate; + + word NumDigi,DigiLeft,DigiPage; + word _seg *DigiList; + word DigiLastStart,DigiLastEnd; + boolean DigiPlaying; +static boolean DigiMissed,DigiLastSegment; +static memptr DigiNextAddr; +static word DigiNextLen; + +// SoundBlaster variables +static boolean sbNoCheck,sbNoProCheck; +static volatile boolean sbSamplePlaying; +static byte sbOldIntMask = -1; +static volatile byte huge *sbNextSegPtr; +static byte sbDMA = 1, + sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3, + sba1Vals[] = {0x87,0x83,0,0x82}, + sba2Vals[] = {0,2,0,6}, + sba3Vals[] = {1,3,0,7}; +static int sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf, + sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1}; +static volatile dword sbNextSegLen; +static volatile SampledSound huge *sbSamples; +static void interrupt (*sbOldIntHand)(void); +static byte sbpOldFMMix,sbpOldVOCMix; + +// SoundSource variables + boolean ssNoCheck; + boolean ssActive; + word ssControl,ssStatus,ssData; + byte ssOn,ssOff; + volatile byte far *ssSample; + volatile dword ssLengthLeft; + +// PC Sound variables + volatile byte pcLastSample,far *pcSound; + dword pcLengthLeft; + word pcSoundLookup[255]; + +// AdLib variables + boolean alNoCheck; + byte far *alSound; + word alBlock; + dword alLengthLeft; + dword alTimeCount; + Instrument alZeroInst; + +// This table maps channel numbers to carrier and modulator op cells +static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21}, + modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18}, +// This table maps percussive voice numbers to op cells + pcarriers[5] = {19,0xff,0xff,0xff,0xff}, + pmodifiers[5] = {16,17,18,20,21}; + +// Sequencer variables + boolean sqActive; +static word alFXReg; +static ActiveTrack *tracks[sqMaxTracks], + mytracks[sqMaxTracks]; +static word sqMode,sqFadeStep; + word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen; + long sqHackTime; + +// Internal routines + void SDL_DigitizedDone(void); + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SetTimer0() - Sets system timer 0 to the specified speed +// +/////////////////////////////////////////////////////////////////////////// +#pragma argsused +static void +SDL_SetTimer0(word speed) +{ +#ifndef TPROF // If using Borland's profiling, don't screw with the timer +asm pushf +asm cli + + outportb(0x43,0x36); // Change timer 0 + outportb(0x40,speed); + outportb(0x40,speed >> 8); + // Kludge to handle special case for digitized PC sounds + if (TimerDivisor == (1192030 / (TickBase * 100))) + TimerDivisor = (1192030 / (TickBase * 10)); + else + TimerDivisor = speed; + +asm popf +#else + TimerDivisor = 0x10000; +#endif +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of +// interrupts generated by system timer 0 per second +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_SetIntsPerSec(word ints) +{ + TimerRate = ints; + SDL_SetTimer0(1192030 / ints); +} + +static void +SDL_SetTimerSpeed(void) +{ + word rate; + void interrupt (*isr)(void); + + if ((DigiMode == sds_PC) && DigiPlaying) + { + rate = TickBase * 100; + isr = SDL_t0ExtremeAsmService; + } + else if + ( + (MusicMode == smm_AdLib) + || ((DigiMode == sds_SoundSource) && DigiPlaying) + ) + { + rate = TickBase * 10; + isr = SDL_t0FastAsmService; + } + else + { + rate = TickBase * 2; + isr = SDL_t0SlowAsmService; + } + + if (rate != TimerRate) + { + setvect(8,isr); + SDL_SetIntsPerSec(rate); + TimerRate = rate; + } +} + +#if 0 +// +// SoundBlaster code +// + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SBStopSample() - Stops any active sampled sound and causes DMA +// requests from the SoundBlaster to cease +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_SBStopSample(void) +{ + byte is; + +asm pushf +asm cli + + if (sbSamplePlaying) + { + sbSamplePlaying = false; + + sbWriteDelay(); + sbOut(sbWriteCmd,0xd0); // Turn off DSP DMA + + is = inportb(0x21); // Restore interrupt mask bit + if (sbOldIntMask & (1 << sbInterrupt)) + is |= (1 << sbInterrupt); + else + is &= ~(1 << sbInterrupt); + outportb(0x21,is); + } + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SBPlaySeg() - Plays a chunk of sampled sound on the SoundBlaster +// Insures that the chunk doesn't cross a bank boundary, programs the DMA +// controller, and tells the SB to start doing DMA requests for DAC +// +/////////////////////////////////////////////////////////////////////////// +static dword +SDL_SBPlaySeg(volatile byte huge *data,dword length) +{ + unsigned datapage; + dword dataofs,uselen; + + uselen = length; + datapage = FP_SEG(data) >> 12; + dataofs = ((FP_SEG(data) & 0xfff) << 4) + FP_OFF(data); + if (dataofs >= 0x10000) + { + datapage++; + dataofs -= 0x10000; + } + + if (dataofs + uselen > 0x10000) + uselen = 0x10000 - dataofs; + + uselen--; + + // Program the DMA controller +asm pushf +asm cli + outportb(0x0a,sbDMA | 4); // Mask off DMA on channel sbDMA + outportb(0x0c,0); // Clear byte ptr flip-flop to lower byte + outportb(0x0b,0x49); // Set transfer mode for D/A conv + outportb(sbDMAa2,(byte)dataofs); // Give LSB of address + outportb(sbDMAa2,(byte)(dataofs >> 8)); // Give MSB of address + outportb(sbDMAa1,(byte)datapage); // Give page of address + outportb(sbDMAa3,(byte)uselen); // Give LSB of length + outportb(sbDMAa3,(byte)(uselen >> 8)); // Give MSB of length + outportb(0x0a,sbDMA); // Re-enable DMA on channel sbDMA + + // Start playing the thing + sbWriteDelay(); + sbOut(sbWriteCmd,0x14); + sbWriteDelay(); + sbOut(sbWriteData,(byte)uselen); + sbWriteDelay(); + sbOut(sbWriteData,(byte)(uselen >> 8)); +asm popf + + return(uselen + 1); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SBService() - Services the SoundBlaster DMA interrupt +// +/////////////////////////////////////////////////////////////////////////// +/*static*/ void interrupt +SDL_SBService(void) +{ + dword used; + + sbIn(sbDataAvail); // Ack interrupt to SB + + if (sbNextSegPtr) + { + used = SDL_SBPlaySeg(sbNextSegPtr,sbNextSegLen); + if (sbNextSegLen <= used) + sbNextSegPtr = nil; + else + { + sbNextSegPtr += used; + sbNextSegLen -= used; + } + } + else + { + SDL_SBStopSample(); + SDL_DigitizedDone(); + } + + outportb(0x20,0x20); // Ack interrupt +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SBPlaySample() - Plays a sampled sound on the SoundBlaster. Sets up +// DMA to play the sound +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_SBPlaySample(byte huge *data,dword len) +{ + dword used; + + SDL_SBStopSample(); + +asm pushf +asm cli + + used = SDL_SBPlaySeg(data,len); + if (len <= used) + sbNextSegPtr = nil; + else + { + sbNextSegPtr = data + used; + sbNextSegLen = len - used; + } + + // Save old interrupt status and unmask ours + sbOldIntMask = inportb(0x21); + outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt)); + + sbWriteDelay(); + sbOut(sbWriteCmd,0xd4); // Make sure DSP DMA is enabled + + sbSamplePlaying = true; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PositionSBP() - Sets the attenuation levels for the left and right +// channels by using the mixer chip on the SB Pro. This hits a hole in +// the address map for normal SBs. +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_PositionSBP(int leftpos,int rightpos) +{ + byte v; + + if (!SBProPresent) + return; + + leftpos = 15 - leftpos; + rightpos = 15 - rightpos; + v = ((leftpos & 0x0f) << 4) | (rightpos & 0x0f); + +asm pushf +asm cli + + sbOut(sbpMixerAddr,sbpmVoiceVol); + sbOut(sbpMixerData,v); + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_CheckSB() - Checks to see if a SoundBlaster resides at a +// particular I/O location +// +/////////////////////////////////////////////////////////////////////////// +static boolean +SDL_CheckSB(int port) +{ + int i; + + sbLocation = port << 4; // Initialize stuff for later use + + sbOut(sbReset,true); // Reset the SoundBlaster DSP +asm mov dx,0x388 // Wait >4usec +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx +asm in al, dx + + sbOut(sbReset,false); // Turn off sb DSP reset +asm mov dx,0x388 // Wait >100usec +asm mov cx,100 +#ifdef __WATCOMC__ + __asm { +#endif +usecloop: +asm in al,dx +asm loop usecloop +#ifdef __WATCOMC__ + } +#endif + + for (i = 0;i < 100;i++) + { + if (sbIn(sbDataAvail) & 0x80) // If data is available... + { + if (sbIn(sbReadData) == 0xaa) // If it matches correct value + return(true); + else + { + sbLocation = -1; // Otherwise not a SoundBlaster + return(false); + } + } + } + sbLocation = -1; // Retry count exceeded - fail + return(false); +} + +/////////////////////////////////////////////////////////////////////////// +// +// Checks to see if a SoundBlaster is in the system. If the port passed is +// -1, then it scans through all possible I/O locations. If the port +// passed is 0, then it uses the default (2). If the port is >0, then +// it just passes it directly to SDL_CheckSB() +// +/////////////////////////////////////////////////////////////////////////// +static boolean +SDL_DetectSoundBlaster(int port) +{ + int i; + + if (port == 0) // If user specifies default, use 2 + port = 2; + if (port == -1) + { + if (SDL_CheckSB(2)) // Check default before scanning + return(true); + + if (SDL_CheckSB(4)) // Check other SB Pro location before scan + return(true); + + for (i = 1;i <= 6;i++) // Scan through possible SB locations + { + if ((i == 2) || (i == 4)) + continue; + + if (SDL_CheckSB(i)) // If found at this address, + return(true); // return success + } + return(false); // All addresses failed, return failure + } + else + return(SDL_CheckSB(port)); // User specified address or default +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SBSetDMA() - Sets the DMA channel to be used by the SoundBlaster +// code. Sets up sbDMA, and sbDMAa1-sbDMAa3 (used by SDL_SBPlaySeg()). +// +/////////////////////////////////////////////////////////////////////////// +void +SDL_SBSetDMA(byte channel) +{ + if (channel > 3) + Quit("SDL_SBSetDMA() - invalid SoundBlaster DMA channel"); + + sbDMA = channel; + sbDMAa1 = sba1Vals[channel]; + sbDMAa2 = sba2Vals[channel]; + sbDMAa3 = sba3Vals[channel]; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_StartSB() - Turns on the SoundBlaster +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_StartSB(void) +{ + byte timevalue,test; + + sbIntVec = sbIntVectors[sbInterrupt]; + if (sbIntVec < 0) + Quit("SDL_StartSB: Illegal or unsupported interrupt number for SoundBlaster"); + + sbOldIntHand = getvect(sbIntVec); // Get old interrupt handler + setvect(sbIntVec,SDL_SBService); // Set mine + + sbWriteDelay(); + sbOut(sbWriteCmd,0xd1); // Turn on DSP speaker + + // Set the SoundBlaster DAC time constant for 7KHz + timevalue = 256 - (1000000 / 7000); + sbWriteDelay(); + sbOut(sbWriteCmd,0x40); + sbWriteDelay(); + sbOut(sbWriteData,timevalue); + + SBProPresent = false; + if (sbNoProCheck) + return; + + // Check to see if this is a SB Pro + sbOut(sbpMixerAddr,sbpmFMVol); + sbpOldFMMix = sbIn(sbpMixerData); + sbOut(sbpMixerData,0xbb); + test = sbIn(sbpMixerData); + if (test == 0xbb) + { + // Boost FM output levels to be equivilent with digitized output + sbOut(sbpMixerData,0xff); + test = sbIn(sbpMixerData); + if (test == 0xff) + { + SBProPresent = true; + + // Save old Voice output levels (SB Pro) + sbOut(sbpMixerAddr,sbpmVoiceVol); + sbpOldVOCMix = sbIn(sbpMixerData); + + // Turn SB Pro stereo DAC off + sbOut(sbpMixerAddr,sbpmControl); + sbOut(sbpMixerData,0); // 0=off,2=on + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ShutSB() - Turns off the SoundBlaster +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_ShutSB(void) +{ + SDL_SBStopSample(); + + if (SBProPresent) + { + // Restore FM output levels (SB Pro) + sbOut(sbpMixerAddr,sbpmFMVol); + sbOut(sbpMixerData,sbpOldFMMix); + + // Restore Voice output levels (SB Pro) + sbOut(sbpMixerAddr,sbpmVoiceVol); + sbOut(sbpMixerData,sbpOldVOCMix); + } + + setvect(sbIntVec,sbOldIntHand); // Set vector back +} +#endif + +// Sound Source Code + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SSStopSample() - Stops a sample playing on the Sound Source +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_SSStopSample(void) +{ +asm pushf +asm cli + + (long)ssSample = 0; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SSService() - Handles playing the next sample on the Sound Source +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_SSService(void) +{ + //boolean gotit; + boolean doneflag=false; + byte v; + + while (ssSample) + { + __asm { + mov dx,[ssStatus] // Check to see if FIFO is currently empty + in al,dx + test al,0x40 + jnz done // Nope - don't push any more data out + jmp end +#ifdef __BORLANDC__ + } +#endif + done: +#ifdef __BORLANDC__ + __asm { +#endif + mov doneflag,1 +#ifdef __BORLANDC__ + } +#endif + end: +#ifdef __WATCOMC__ + } +#endif + if(!doneflag) + { + v = *ssSample++; + if (!(--ssLengthLeft)) + { + (long)ssSample = 0; + SDL_DigitizedDone(); + } + + __asm { + mov dx,[ssData] // Pump the value out + mov al,[v] + out dx,al + + mov dx,[ssControl] // Pulse printer select + mov al,[ssOff] + out dx,al + push ax + pop ax + mov al,[ssOn] + out dx,al + + push ax // Delay a short while + pop ax + push ax + pop ax +done:; + } + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SSPlaySample() - Plays the specified sample on the Sound Source +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_SSPlaySample(byte huge *data,dword len) +{ +asm pushf +asm cli + + ssLengthLeft = len; + ssSample = (volatile byte far *)data; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_StartSS() - Sets up for and turns on the Sound Source +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_StartSS(void) +{ + if (ssPort == 3) + ssControl = 0x27a; // If using LPT3 + else if (ssPort == 2) + ssControl = 0x37a; // If using LPT2 + else + ssControl = 0x3be; // If using LPT1 + ssStatus = ssControl - 1; + ssData = ssStatus - 1; + + ssOn = 0x04; + if (ssIsTandy) + ssOff = 0x0e; // Tandy wierdness + else + ssOff = 0x0c; // For normal machines + + outportb(ssControl,ssOn); // Enable SS +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ShutSS() - Turns off the Sound Source +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_ShutSS(void) +{ + outportb(ssControl,ssOff); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_CheckSS() - Checks to see if a Sound Source is present at the +// location specified by the sound source variables +// +/////////////////////////////////////////////////////////////////////////// +static boolean +SDL_CheckSS(void) +{ + boolean present = false, chkdone=0; + dword lasttime; + + // Turn the Sound Source on and wait awhile (4 ticks) + SDL_StartSS(); + + lasttime = TimeCount; + while (TimeCount < lasttime + 4) + {} + + __asm { + mov dx,[ssStatus] // Check to see if FIFO is currently empty + in al,dx + test al,0x40 + jnz checkdone // Nope - Sound Source not here + + mov cx,32 // Force FIFO overflow (FIFO is 16 bytes) +#ifdef __BORLANDC__ + } +#endif +outloop: +#ifdef __BORLANDC__ + __asm { +#endif + mov dx,[ssData] // Pump a neutral value out + mov al,0x80 + out dx,al + + mov dx,[ssControl] // Pulse printer select + mov al,[ssOff] + out dx,al + push ax + pop ax + mov al,[ssOn] + out dx,al + + push ax // Delay a short while before we do this again + pop ax + push ax + pop ax + + loop outloop + + mov dx,[ssStatus] // Is FIFO overflowed now? + in al,dx + test al,0x40 + jz checkdone // Nope, still not - Sound Source not here + jmp end +#ifdef __BORLANDC__ + } +#endif +checkdone: +#ifdef __BORLANDC__ + __asm { +#endif + mov chkdone,1 +#ifdef __BORLANDC__ + } +#endif + end: +#ifdef __WATCOMC__ + } +#endif + + if(!chkdone) present = true; // Yes - it's here! + +//checkdone: + SDL_ShutSS(); + return(present); +} + +static boolean +SDL_DetectSoundSource(void) +{ + for (ssPort = 1;ssPort <= 3;ssPort++) + if (SDL_CheckSS()) + return(true); + return(false); +} + +// +// PC Sound code +// + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PCPlaySample() - Plays the specified sample on the PC speaker +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_PCPlaySample(byte huge *data,dword len) +{ +asm pushf +asm cli + + SDL_IndicatePC(true); + + pcLengthLeft = len; + pcSound = (volatile byte far *)data; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PCStopSample() - Stops a sample playing on the PC speaker +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_PCStopSample(void) +{ +asm pushf +asm cli + + (long)pcSound = 0; + + SDL_IndicatePC(false); + +asm in al,0x61 // Turn the speaker off +asm and al,0xfd // ~2 +asm out 0x61,al + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PCPlaySound() - Plays the specified sound on the PC speaker +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_PCPlaySound(PCSound far *sound) +{ +asm pushf +asm cli + + pcLastSample = -1; + pcLengthLeft = sound->common.length; + pcSound = sound->data; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_PCStopSound(void) +{ +asm pushf +asm cli + + (long)pcSound = 0; + +asm in al,0x61 // Turn the speaker off +asm and al,0xfd // ~2 +asm out 0x61,al + +asm popf +} + +#if 0 +/////////////////////////////////////////////////////////////////////////// +// +// SDL_PCService() - Handles playing the next sample in a PC sound +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_PCService(void) +{ + byte s; + word t; + + if (pcSound) + { + s = *pcSound++; + if (s != pcLastSample) + { + asm pushf + asm cli + + pcLastSample = s; + if (s) // We have a frequency! + { + t = pcSoundLookup[s]; + asm mov bx,[t] + + asm mov al,0xb6 // Write to channel 2 (speaker) timer + asm out 43h,al + asm mov al,bl + asm out 42h,al // Low byte + asm mov al,bh + asm out 42h,al // High byte + + asm in al,0x61 // Turn the speaker & gate on + asm or al,3 + asm out 0x61,al + } + else // Time for some silence + { + asm in al,0x61 // Turn the speaker & gate off + asm and al,0xfc // ~3 + asm out 0x61,al + } + + asm popf + } + + if (!(--pcLengthLeft)) + { + SDL_PCStopSound(); + SDL_SoundFinished(); + } + } +} +#endif + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ShutPC() - Turns off the pc speaker +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_ShutPC(void) +{ +asm pushf +asm cli + + pcSound = 0; + +asm in al,0x61 // Turn the speaker & gate off +asm and al,0xfc // ~3 +asm out 0x61,al + +asm popf +} + +// +// Stuff for digitized sounds +// +memptr +SDL_LoadDigiSegment(word page) +{ + memptr addr; + +#if 0 // for debugging +asm mov dx,STATUS_REGISTER_1 +asm in al,dx +asm mov dx,ATR_INDEX +asm mov al,ATR_OVERSCAN +asm out dx,al +asm mov al,10 // bright green +asm out dx,al +#endif + + addr = PM_GetSoundPage(page, gvar); + PM_SetPageLock(PMSoundStart + page,pml_Locked); + +#if 0 // for debugging +asm mov dx,STATUS_REGISTER_1 +asm in al,dx +asm mov dx,ATR_INDEX +asm mov al,ATR_OVERSCAN +asm out dx,al +asm mov al,3 // blue +asm out dx,al +asm mov al,0x20 // normal +asm out dx,al +#endif + + return(addr); +} + +void +SDL_PlayDigiSegment(memptr addr,word len) +{ + switch (DigiMode) + { + case sds_PC: + SDL_PCPlaySample(addr,len); + break; + case sds_SoundSource: + SDL_SSPlaySample(addr,len); + break; + case sds_SoundBlaster: + SDL_SBPlaySample(addr,len); + break; + } +} + +void +SD_StopDigitized(void) +{ + int i; + +asm pushf +asm cli + + DigiLeft = 0; + DigiNextAddr = nil; + DigiNextLen = 0; + DigiMissed = false; + DigiPlaying = false; + DigiNumber = DigiPriority = 0; + SoundPositioned = false; + if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) + SDL_SoundFinished(); + + switch (DigiMode) + { + case sds_PC: + SDL_PCStopSample(); + break; + case sds_SoundSource: + SDL_SSStopSample(); + break; + case sds_SoundBlaster: + SDL_SBStopSample(); + break; + } + +asm popf + + for (i = DigiLastStart;i < DigiLastEnd;i++) + PM_SetPageLock(i + PMSoundStart,pml_Unlocked); + DigiLastStart = 1; + DigiLastEnd = 0; +} + +void +SD_Poll(void) +{ + if (DigiLeft && !DigiNextAddr) + { + DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize); + DigiLeft -= DigiNextLen; + if (!DigiLeft) + DigiLastSegment = true; + DigiNextAddr = SDL_LoadDigiSegment(DigiPage++); + } + if (DigiMissed && DigiNextAddr) + { + SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen); + DigiNextAddr = nil; + DigiMissed = false; + if (DigiLastSegment) + { + DigiPlaying = false; + DigiLastSegment = false; + } + } + SDL_SetTimerSpeed(); +} + +void +SD_SetPosition(int leftpos,int rightpos) +{ + if + ( + (leftpos < 0) + || (leftpos > 15) + || (rightpos < 0) + || (rightpos > 15) + || ((leftpos == 15) && (rightpos == 15)) + ) + Quit("SD_SetPosition: Illegal position"); + + switch (DigiMode) + { + case sds_SoundBlaster: + SDL_PositionSBP(leftpos,rightpos); + break; + } +} + +void +SD_PlayDigitized(word which,int leftpos,int rightpos) +{ + word len; + memptr addr; + + if (!DigiMode) + return; + + SD_StopDigitized(); + if (which >= NumDigi) + Quit("SD_PlayDigitized: bad sound number"); + + SD_SetPosition(leftpos,rightpos); + + DigiPage = DigiList[(which * 2) + 0]; + DigiLeft = DigiList[(which * 2) + 1]; + + DigiLastStart = DigiPage; + DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize); + + len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize); + addr = SDL_LoadDigiSegment(DigiPage++); + + DigiPlaying = true; + DigiLastSegment = false; + + SDL_PlayDigiSegment(addr,len); + DigiLeft -= len; + if (!DigiLeft) + DigiLastSegment = true; + + SD_Poll(); +} + +void +SDL_DigitizedDone(void) +{ + if (DigiNextAddr) + { + SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen); + DigiNextAddr = nil; + DigiMissed = false; + } + else + { + if (DigiLastSegment) + { + DigiPlaying = false; + DigiLastSegment = false; + if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) + { + SDL_SoundFinished(); + } + else + DigiNumber = DigiPriority = 0; + SoundPositioned = false; + } + else + DigiMissed = true; + } +} + +void +SD_SetDigiDevice(SDSMode mode) +{ + boolean devicenotpresent; + + if (mode == DigiMode) + return; + + SD_StopDigitized(); + + devicenotpresent = false; + switch (mode) + { + case sds_SoundBlaster: + if (!SoundBlasterPresent) + { + if (SoundSourcePresent) + mode = sds_SoundSource; + else + devicenotpresent = true; + } + break; + case sds_SoundSource: + if (!SoundSourcePresent) + devicenotpresent = true; + break; + } + + if (!devicenotpresent) + { + if (DigiMode == sds_SoundSource) + SDL_ShutSS(); + + DigiMode = mode; + + if (mode == sds_SoundSource) + SDL_StartSS(); + + SDL_SetTimerSpeed(); + } +} + +void +SDL_SetupDigi(void) +{ + memptr list; + word far *p, + pg; + int i; + + PM_UnlockMainMem(); + MM_GetPtr(&list,PMPageSize); + PM_CheckMainMem(); + p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0); + _fmemcpy((void far *)list,(void far *)p,PMPageSize); + pg = PMSoundStart; + for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2) + { + if (pg >= ChunksInFile - 1) + break; + pg += (p[1] + (PMPageSize - 1)) / PMPageSize; + } + PM_UnlockMainMem(); + MM_GetPtr((memptr *)&DigiList,i * sizeof(word) * 2); + _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2); + MM_FreePtr(&list); + NumDigi = i; + + for (i = 0;i < LASTSOUND;i++) + DigiMap[i] = -1; +} + +// AdLib Code + +/////////////////////////////////////////////////////////////////////////// +// +// alOut(n,b) - Puts b in AdLib card register n +// +/////////////////////////////////////////////////////////////////////////// +void +alOut(byte n,byte b) +{ +asm pushf +asm cli + +asm mov dx,0x388 +asm mov al,[n] +asm out dx,al +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm inc dx +asm mov al,[b] +asm out dx,al + +asm popf + +asm dec dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx + +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx + +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx + +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +asm in al,dx +} + +#if 0 +/////////////////////////////////////////////////////////////////////////// +// +// SDL_SetInstrument() - Puts an instrument into a generator +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive) +{ + byte c,m; + + if (percussive) + { + c = pcarriers[which]; + m = pmodifiers[which]; + } + else + { + c = carriers[which]; + m = modifiers[which]; + } + + tracks[track - 1]->inst = *inst; + tracks[track - 1]->percussive = percussive; + + alOut(m + alChar,inst->mChar); + alOut(m + alScale,inst->mScale); + alOut(m + alAttack,inst->mAttack); + alOut(m + alSus,inst->mSus); + alOut(m + alWave,inst->mWave); + + // Most percussive instruments only use one cell + if (c != 0xff) + { + alOut(c + alChar,inst->cChar); + alOut(c + alScale,inst->cScale); + alOut(c + alAttack,inst->cAttack); + alOut(c + alSus,inst->cSus); + alOut(c + alWave,inst->cWave); + } + + alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right +} +#endif + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ALStopSound() - Turns off any sound effects playing through the +// AdLib card +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_ALStopSound(void) +{ +asm pushf +asm cli + + (long)alSound = 0; + alOut(alFreqH + 0,0); + +asm popf +} + +static void +SDL_AlSetFXInst(Instrument far *inst) +{ + byte c,m; + + m = modifiers[0]; + c = carriers[0]; + alOut(m + alChar,inst->mChar); + alOut(m + alScale,inst->mScale); + alOut(m + alAttack,inst->mAttack); + alOut(m + alSus,inst->mSus); + alOut(m + alWave,inst->mWave); + alOut(c + alChar,inst->cChar); + alOut(c + alScale,inst->cScale); + alOut(c + alAttack,inst->cAttack); + alOut(c + alSus,inst->cSus); + alOut(c + alWave,inst->cWave); + + // Note: Switch commenting on these lines for old MUSE compatibility +// alOut(alFeedCon,inst->nConn); + alOut(alFeedCon,0); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ALPlaySound() - Plays the specified sound on the AdLib card +// +/////////////////////////////////////////////////////////////////////////// +#ifdef _MUSE_ +void +#else +static void +#endif +SDL_ALPlaySound(AdLibSound far *sound) +{ + Instrument far *inst; + byte huge *data; + + SDL_ALStopSound(); + +asm pushf +asm cli + + alLengthLeft = sound->common.length; + data = sound->data; + data++; + data--; + alSound = (byte far *)data; + alBlock = ((sound->block & 7) << 2) | 0x20; + inst = &sound->inst; + + if (!(inst->mSus | inst->cSus)) + { + asm popf + Quit("SDL_ALPlaySound() - Bad instrument"); + } + + SDL_AlSetFXInst(&alZeroInst); // DEBUG + SDL_AlSetFXInst(inst); + +asm popf +} + +#if 0 +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ALSoundService() - Plays the next sample out through the AdLib card +// +/////////////////////////////////////////////////////////////////////////// +//static void +void +SDL_ALSoundService(void) +{ + byte s; + + if (alSound) + { + s = *alSound++; + if (!s) + alOut(alFreqH + 0,0); + else + { + alOut(alFreqL + 0,s); + alOut(alFreqH + 0,alBlock); + } + + if (!(--alLengthLeft)) + { + (long)alSound = 0; + alOut(alFreqH + 0,0); + SDL_SoundFinished(); + } + } +} +#endif + +#if 0 +void +SDL_ALService(void) +{ + byte a,v; + word w; + + if (!sqActive) + return; + + while (sqHackLen && (sqHackTime <= alTimeCount)) + { + w = *sqHackPtr++; + sqHackTime = alTimeCount + *sqHackPtr++; + asm mov dx,[w] + asm mov [a],dl + asm mov [v],dh + alOut(a,v); + sqHackLen -= 4; + } + alTimeCount++; + if (!sqHackLen) + { + sqHackPtr = (word far *)sqHack; + sqHackLen = sqHackSeqLen; + alTimeCount = sqHackTime = 0; + } +} +#endif + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_ShutAL() - Shuts down the AdLib card for sound effects +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_ShutAL(void) +{ +asm pushf +asm cli + + alOut(alEffects,0); + alOut(alFreqH + 0,0); + SDL_AlSetFXInst(&alZeroInst); + alSound = 0; + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_CleanAL() - Totally shuts down the AdLib card +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_CleanAL(void) +{ + int i; + +asm pushf +asm cli + + alOut(alEffects,0); + for (i = 1;i < 0xf5;i++) + alOut(i,0); + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_StartAL() - Starts up the AdLib card for sound effects +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_StartAL(void) +{ + alFXReg = 0; + alOut(alEffects,alFXReg); + SDL_AlSetFXInst(&alZeroInst); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster +// emulating an AdLib) present +// +/////////////////////////////////////////////////////////////////////////// +static boolean +SDL_DetectAdLib(void) +{ + byte status1,status2; + int i; + + alOut(4,0x60); // Reset T1 & T2 + alOut(4,0x80); // Reset IRQ + status1 = readstat(); + alOut(2,0xff); // Set timer 1 + alOut(4,0x21); // Start timer 1 +#if 0 + SDL_Delay(TimerDelay100); +#else + __asm { + mov dx,0x388 + mov cx,100 +#ifdef __BORLANDC__ + } +#endif +usecloop: +#ifdef __BORLANDC__ + __asm { +#endif + in al,dx + loop usecloop + } +#endif + + status2 = readstat(); + alOut(4,0x60); + alOut(4,0x80); + + if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0)) + { + for (i = 1;i <= 0xf5;i++) // Zero all the registers + alOut(i,0); + + alOut(1,0x20); // Set WSE=1 + alOut(8,0); // Set CSM=0 & SEL=0 + + return(true); + } + else + return(false); +} + +#if 0 +/////////////////////////////////////////////////////////////////////////// +// +// SDL_t0Service() - My timer 0 ISR which handles the different timings and +// dispatches to whatever other routines are appropriate +// +/////////////////////////////////////////////////////////////////////////// +static void interrupt +SDL_t0Service(void) +{ +static word count = 1; + +#if 1 // for debugging +asm mov dx,STATUS_REGISTER_1 +asm in al,dx +asm mov dx,ATR_INDEX +asm mov al,ATR_OVERSCAN +asm out dx,al +asm mov al,4 // red +asm out dx,al +#endif + + HackCount++; + + if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource)) + { + SDL_ALService(); + SDL_SSService(); +// if (!(++count & 7)) + if (!(++count % 10)) + { + LocalTime++; + TimeCount++; + if (SoundUserHook) + SoundUserHook(); + } +// if (!(count & 3)) + if (!(count % 5)) + { + switch (SoundMode) + { + case sdm_PC: + SDL_PCService(); + break; + case sdm_AdLib: + SDL_ALSoundService(); + break; + } + } + } + else + { + if (!(++count & 1)) + { + LocalTime++; + TimeCount++; + if (SoundUserHook) + SoundUserHook(); + } + switch (SoundMode) + { + case sdm_PC: + SDL_PCService(); + break; + case sdm_AdLib: + SDL_ALSoundService(); + break; + } + } + +asm mov ax,[WORD PTR TimerCount] +asm add ax,[WORD PTR TimerDivisor] +asm mov [WORD PTR TimerCount],ax +asm jnc myack + t0OldService(); // If we overflow a word, time to call old int handler +asm jmp olddone +myack:; + outportb(0x20,0x20); // Ack the interrupt +olddone:; + +#if 1 // for debugging +asm mov dx,STATUS_REGISTER_1 +asm in al,dx +asm mov dx,ATR_INDEX +asm mov al,ATR_OVERSCAN +asm out dx,al +asm mov al,3 // blue +asm out dx,al +asm mov al,0x20 // normal +asm out dx,al +#endif +} +#endif + +//////////////////////////////////////////////////////////////////////////// +// +// SDL_ShutDevice() - turns off whatever device was being used for sound fx +// +//////////////////////////////////////////////////////////////////////////// +static void +SDL_ShutDevice(void) +{ + switch (SoundMode) + { + case sdm_PC: + SDL_ShutPC(); + break; + case sdm_AdLib: + SDL_ShutAL(); + break; + } + SoundMode = sdm_Off; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_CleanDevice() - totally shuts down all sound devices +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_CleanDevice(void) +{ + if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib)) + SDL_CleanAL(); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDL_StartDevice() - turns on whatever device is to be used for sound fx +// +/////////////////////////////////////////////////////////////////////////// +static void +SDL_StartDevice(void) +{ + switch (SoundMode) + { + case sdm_AdLib: + SDL_StartAL(); + break; + } + SoundNumber = SoundPriority = 0; +} + +// Public routines + +/////////////////////////////////////////////////////////////////////////// +// +// SD_SetSoundMode() - Sets which sound hardware to use for sound effects +// +/////////////////////////////////////////////////////////////////////////// +boolean +SD_SetSoundMode(SDMode mode) +{ + boolean result = false; + word tableoffset; + + SD_StopSound(); + +#ifndef _MUSE_ + if ((mode == sdm_AdLib) && !AdLibPresent) + mode = sdm_PC; + + switch (mode) + { + case sdm_Off: + NeedsDigitized = false; + result = true; + break; + case sdm_PC: + tableoffset = STARTPCSOUNDS; + NeedsDigitized = false; + result = true; + break; + case sdm_AdLib: + if (AdLibPresent) + { + tableoffset = STARTADLIBSOUNDS; + NeedsDigitized = false; + result = true; + } + break; + } +#else + result = true; +#endif + + if (result && (mode != SoundMode)) + { + SDL_ShutDevice(); + SoundMode = mode; +#ifndef _MUSE_ + SoundTable = (word *)(&audiosegs[tableoffset]); +#endif + SDL_StartDevice(); + } + + SDL_SetTimerSpeed(); + + return(result); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_SetMusicMode() - sets the device to use for background music +// +/////////////////////////////////////////////////////////////////////////// +boolean +SD_SetMusicMode(SMMode mode) +{ + boolean result = false; + + SD_FadeOutMusic(); + while (SD_MusicPlaying()) + ; + + switch (mode) + { + case smm_Off: + NeedsMusic = false; + result = true; + break; + case smm_AdLib: + if (AdLibPresent) + { + NeedsMusic = true; + result = true; + } + break; + } + + if (result) + MusicMode = mode; + + SDL_SetTimerSpeed(); + + return(result); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_Startup() - starts up the Sound Mgr +// Detects all additional sound hardware and installs my ISR +// +/////////////////////////////////////////////////////////////////////////// +void +SD_Startup(void) +{ + int i; + + if (SD_Started) + return; + + SDL_SetDS(); + + ssIsTandy = false; + ssNoCheck = false; + alNoCheck = false; + sbNoCheck = false; + sbNoProCheck = false; +#ifndef _MUSE_ + for (i = 1;i < _argc;i++) + { + switch (US_CheckParm(_argv[i],ParmStrings)) + { + case 0: // No AdLib detection + alNoCheck = true; + break; + case 1: // No SoundBlaster detection + sbNoCheck = true; + break; + case 2: // No SoundBlaster Pro detection + sbNoProCheck = true; + break; + case 3: + ssNoCheck = true; // No Sound Source detection + break; + case 4: // Tandy Sound Source handling + ssIsTandy = true; + break; + case 5: // Sound Source present at LPT1 + ssPort = 1; + ssNoCheck = SoundSourcePresent = true; + break; + case 6: // Sound Source present at LPT2 + ssPort = 2; + ssNoCheck = SoundSourcePresent = true; + break; + case 7: // Sound Source present at LPT3 + ssPort = 3; + ssNoCheck = SoundSourcePresent = true; + break; + } + } +#endif + + SoundUserHook = 0; + + t0OldService = getvect(8); // Get old timer 0 ISR + + LocalTime = TimeCount = alTimeCount = 0; + + SD_SetSoundMode(sdm_Off); + SD_SetMusicMode(smm_Off); + + if (!ssNoCheck) + SoundSourcePresent = SDL_DetectSoundSource(); + + if (!alNoCheck) + { + AdLibPresent = SDL_DetectAdLib(); + if (AdLibPresent && !sbNoCheck) + { + int port = -1; + char *env = getenv("BLASTER"); + if (env) + { + long temp; + while (*env) + { + while (isspace(*env)) + env++; + + switch (toupper(*env)) + { + case 'A': + temp = strtol(env + 1,&env,16); + if + ( + (temp >= 0x210) + && (temp <= 0x260) + && (!(temp & 0x00f)) + ) + port = (temp - 0x200) >> 4; + else + Quit("SD_Startup: Unsupported address value in BLASTER"); + break; + case 'I': + temp = strtol(env + 1,&env,10); + if + ( + (temp >= 0) + && (temp <= 10) + && (sbIntVectors[temp] != -1) + ) + { + sbInterrupt = temp; + sbIntVec = sbIntVectors[sbInterrupt]; + } + else + Quit("SD_Startup: Unsupported interrupt value in BLASTER"); + break; + case 'D': + temp = strtol(env + 1,&env,10); + if ((temp == 0) || (temp == 1) || (temp == 3)) + SDL_SBSetDMA(temp); + else + Quit("SD_Startup: Unsupported DMA value in BLASTER"); + break; + default: + while (isspace(*env)) + env++; + while (*env && !isspace(*env)) + env++; + break; + } + } + } + SoundBlasterPresent = SDL_DetectSoundBlaster(port); + } + } + + for (i = 0;i < 255;i++) + pcSoundLookup[i] = i * 60; + + if (SoundBlasterPresent) + SDL_StartSB(); + + SDL_SetupDigi(); + + SD_Started = true; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_Default() - Sets up the default behaviour for the Sound Mgr whether +// the config file was present or not. +// +/////////////////////////////////////////////////////////////////////////// +void +SD_Default(boolean gotit,SDMode sd,SMMode sm) +{ + boolean gotsd,gotsm; + + gotsd = gotsm = gotit; + + if (gotsd) // Make sure requested sound hardware is available + { + switch (sd) + { + case sdm_AdLib: + gotsd = AdLibPresent; + break; + } + } + if (!gotsd) + { + if (AdLibPresent) + sd = sdm_AdLib; + else + sd = sdm_PC; + } + if (sd != SoundMode) + SD_SetSoundMode(sd); + + + if (gotsm) // Make sure requested music hardware is available + { + switch (sm) + { + case sdm_AdLib: + gotsm = AdLibPresent; + break; + } + } + if (!gotsm) + { + if (AdLibPresent) + sm = smm_AdLib; + } + if (sm != MusicMode) + SD_SetMusicMode(sm); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_Shutdown() - shuts down the Sound Mgr +// Removes sound ISR and turns off whatever sound hardware was active +// +/////////////////////////////////////////////////////////////////////////// +void +SD_Shutdown(void) +{ + if (!SD_Started) + return; + + SD_MusicOff(); + SD_StopSound(); + SDL_ShutDevice(); + SDL_CleanDevice(); + + if (SoundBlasterPresent) + SDL_ShutSB(); + + if (SoundSourcePresent) + SDL_ShutSS(); + + asm pushf + asm cli + + SDL_SetTimer0(0); + + setvect(8,t0OldService); + + asm popf + + SD_Started = false; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th +// of a second from its timer 0 ISR +// +/////////////////////////////////////////////////////////////////////////// +void +SD_SetUserHook(void (* hook)(void)) +{ + SoundUserHook = hook; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_PositionSound() - Sets up a stereo imaging location for the next +// sound to be played. Each channel ranges from 0 to 15. +// +/////////////////////////////////////////////////////////////////////////// +void +SD_PositionSound(int leftvol,int rightvol) +{ + LeftPosition = leftvol; + RightPosition = rightvol; + nextsoundpos = true; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_PlaySound() - plays the specified sound on the appropriate hardware +// +/////////////////////////////////////////////////////////////////////////// +boolean +SD_PlaySound(soundnames sound) +{ + boolean ispos; + SoundCommon far *s; + int lp,rp; + + lp = LeftPosition; + rp = RightPosition; + LeftPosition = 0; + RightPosition = 0; + + ispos = nextsoundpos; + nextsoundpos = false; + + if (sound == -1) + return(false); + + s = MK_FP(SoundTable[sound],0); + if ((SoundMode != sdm_Off) && !s) + Quit("SD_PlaySound() - Uncached sound"); + + if ((DigiMode != sds_Off) && (DigiMap[sound] != -1)) + { + if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) + { + if (s->priority < SoundPriority) + return(false); + + SDL_PCStopSound(); + + SD_PlayDigitized(DigiMap[sound],lp,rp); + SoundPositioned = ispos; + SoundNumber = sound; + SoundPriority = s->priority; + } + else + { + asm pushf + asm cli + if (DigiPriority && !DigiNumber) + { + asm popf + Quit("SD_PlaySound: Priority without a sound"); + } + asm popf + + if (s->priority < DigiPriority) + return(false); + + SD_PlayDigitized(DigiMap[sound],lp,rp); + SoundPositioned = ispos; + DigiNumber = sound; + DigiPriority = s->priority; + } + + return(true); + } + + if (SoundMode == sdm_Off) + return(false); + if (!s->length) + Quit("SD_PlaySound() - Zero length sound"); + if (s->priority < SoundPriority) + return(false); + + switch (SoundMode) + { + case sdm_PC: + SDL_PCPlaySound((void far *)s); + break; + case sdm_AdLib: + SDL_ALPlaySound((void far *)s); + break; + } + + SoundNumber = sound; + SoundPriority = s->priority; + + return(false); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_SoundPlaying() - returns the sound number that's playing, or 0 if +// no sound is playing +// +/////////////////////////////////////////////////////////////////////////// +word +SD_SoundPlaying(void) +{ + boolean result = false; + + switch (SoundMode) + { + case sdm_PC: + result = pcSound? true : false; + break; + case sdm_AdLib: + result = alSound? true : false; + break; + } + + if (result) + return(SoundNumber); + else + return(false); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_StopSound() - if a sound is playing, stops it +// +/////////////////////////////////////////////////////////////////////////// +void +SD_StopSound(void) +{ + if (DigiPlaying) + SD_StopDigitized(); + + switch (SoundMode) + { + case sdm_PC: + SDL_PCStopSound(); + break; + case sdm_AdLib: + SDL_ALStopSound(); + break; + } + + SoundPositioned = false; + + SDL_SoundFinished(); +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_WaitSoundDone() - waits until the current sound is done playing +// +/////////////////////////////////////////////////////////////////////////// +void +SD_WaitSoundDone(void) +{ + while (SD_SoundPlaying()) + ; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_MusicOn() - turns on the sequencer +// +/////////////////////////////////////////////////////////////////////////// +void +SD_MusicOn(void) +{ + sqActive = true; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_MusicOff() - turns off the sequencer and any playing notes +// +/////////////////////////////////////////////////////////////////////////// +void +SD_MusicOff(void) +{ + word i; + + + switch (MusicMode) + { + case smm_AdLib: + alFXReg = 0; + alOut(alEffects,0); + for (i = 0;i < sqMaxTracks;i++) + alOut(alFreqH + i + 1,0); + break; + } + sqActive = false; +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_StartMusic() - starts playing the music pointed to +// +/////////////////////////////////////////////////////////////////////////// +void +SD_StartMusic(MusicGroup far *music) +{ + SD_MusicOff(); +asm pushf +asm cli + + if (MusicMode == smm_AdLib) + { + sqHackPtr = sqHack = music->values; + sqHackSeqLen = sqHackLen = music->length; + sqHackTime = 0; + alTimeCount = 0; + SD_MusicOn(); + } + +asm popf +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying() +// to see if the fadeout is complete +// +/////////////////////////////////////////////////////////////////////////// +void +SD_FadeOutMusic(void) +{ + switch (MusicMode) + { + case smm_AdLib: + // DEBUG - quick hack to turn the music off + SD_MusicOff(); + break; + } +} + +/////////////////////////////////////////////////////////////////////////// +// +// SD_MusicPlaying() - returns true if music is currently playing, false if +// not +// +/////////////////////////////////////////////////////////////////////////// +boolean +SD_MusicPlaying(void) +{ + boolean result; + + switch (MusicMode) + { + case smm_AdLib: + result = false; + // DEBUG - not written + break; + default: + result = false; + } + + return(result); +} + +// SD ASS! +void SDL_SetDS() +{ + __asm { + mov ax,ds + mov [cs:MyDS],ds + ret + } +} + +void SDL_turnOnPCSpeaker(word timerval) +{ + __asm { + mov bx,timerval + mov al,0b6h + out 43h,al + mov al,bl + out 42h,al + mov al,bh + out 42h,al + in al,61h + or al,3 + out 61h,al + } +} + +void SDL_turnOffPCSpeaker() +{ + __asm { + in al,61h + and al,0fch + out 61h,al + } +} + +void SDL_setPCSpeaker(byte val) +{ + __asm { + mov al,val + in al,61h + and al,0fch + or al,ah + out 61h,al + } +} + +void SDL_DoFX() +{ + if(pcSound) + { + if(*pcSound!=pcLastSample) + { + pcLastSample=*pcSound; + + if(pcLastSample) + SDL_turnOnPCSpeaker(pcLastSample*60); + else + SDL_turnOffPCSpeaker(); + } + pcSound++; + pcLengthLeft--; + if(!pcLengthLeft) + { + pcSound=0; + SoundNumber=(soundnames)0; + SoundPriority=0; + SDL_turnOffPCSpeaker(); + } + } + + if(alSound && !alNoIRQ) + { + if(*alSound) + { + alOutInIRQ(alFreqL,*alSound); + alOutInIRQ(alFreqH,alBlock); + } + else alOutInIRQ(alFreqH,0); + alSound++; + alLengthLeft--; + if(!alLengthLeft) + { + alSound=0; + SoundNumber=(soundnames)0; + SoundPriority=0; + alOutInIRQ(alFreqH,0); + } + } + +} + +void SDL_DoFast() +{ + count_fx++; + if(count_fx>=5) + { + count_fx=0; + + SDL_DoFX(); + + count_time++; + if(count_time>=2) + { + TimeCount++; + count_time=0; + } + } + + if(sqActive && !alNoIRQ) + { + if(sqHackLen) + { + do + { + if(sqHackTime>alTimeCount) break; + sqHackTime=alTimeCount+*(sqHackPtr+1); + alOutInIRQ(*(byte *)sqHackPtr,*(((byte *)sqHackPtr)+1)); + sqHackPtr+=2; + sqHackLen-=4; + } + while(sqHackLen); + } + alTimeCount++; + if(!sqHackLen) + { + sqHackPtr=sqHack; + sqHackLen=sqHackSeqLen; + alTimeCount=0; + sqHackTime=0; + } + } + + if(ssSample) + { + if(!(inp(ssStatus)&0x40)) + { + outp(ssData,*ssSample++); + outp(ssControl,ssOff); + __asm push ax + __asm pop ax + outp(ssControl,ssOn); + __asm push ax + __asm pop ax + ssLengthLeft--; + if(!ssLengthLeft) + { + ssSample=0; + SDL_DigitizedDoneInIRQ(); + } + } + } + + TimerCount+=TimerDivisor; + if(*((word *)&TimerCount+1)) + { + *((word *)&TimerCount+1)=0; + t0OldService(); + } + else + { + outp(0x20,0x20); + } +} + +// Timer 0 ISR for 7000Hz interrupts +void interrupt SDL_t0ExtremeAsmService(void) +{ + if(pcindicate) + { + if(pcSound) + { + SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); + pcLengthLeft--; + if(!pcLengthLeft) + { + pcSound=0; + SDL_turnOffPCSpeaker(); + SDL_DigitizedDoneInIRQ(); + } + } + } + extreme++; + if(extreme>=10) + { + extreme=0; + SDL_DoFast(); + } + else + outp(0x20,0x20); +} + +// Timer 0 ISR for 7000Hz interrupts +void interrupt __SDL_t0ExtremeAsmService() +{ + if(pcindicate) + { + if(pcSound) + { + SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); + pcLengthLeft--; + if(!pcLengthLeft) + { + pcSound=0; + SDL_turnOffPCSpeaker(); + SDL_DigitizedDoneInIRQ(); + } + } + } + extreme++; + if(extreme>=10) + { + extreme=0; + SDL_DoFast(); + } + else + outp(0x20,0x20); +} + +// Timer 0 ISR for 700Hz interrupts +void interrupt SDL_t0FastAsmService(void) +{ + SDL_DoFast(); +} + +// Timer 0 ISR for 140Hz interrupts +void interrupt SDL_t0SlowAsmService(void) +{ + count_time++; + if(count_time>=2) + { + TimeCount++; + count_time=0; + } + + SDL_DoFX(); + + TimerCount+=TimerDivisor; + if(*((word *)&TimerCount+1)) + { + *((word *)&TimerCount+1)=0; + t0OldService(); + } + else + outp(0x20,0x20); +} + +void SDL_IndicatePC(boolean ind) +{ + pcindicate=ind; +} + +void +SDL_DigitizedDoneInIRQ(void) +{ + if (DigiNextAddr) + { + SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen/*,true*/); + DigiNextAddr = nil; + DigiMissed = false; + } + else + { + if (DigiLastSegment) + { + DigiPlaying = false; + DigiLastSegment = false; + if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) + { + SDL_SoundFinished(); + } + else + { + DigiNumber = (soundnames) 0; + DigiPriority = 0; + } + SoundPositioned = false; + } + else + DigiMissed = true; + } +} + +// Inside an interrupt handler interrupts should already be disabled +// so don't disable them again and cause V86 exceptions which cost +// aprox. 300 processor tics! + +//static +void alOutInIRQ(byte n,byte b) +{ + __asm { + mov dx,0x388 + mov al,[n] + out dx,al + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + inc dx + mov al,[b] + out dx,al + + dec dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + + in al,dx + in al,dx + in al,dx + in al,dx + in al,dx + } +} + diff --git a/src/lib/id_sd.h b/src/lib/id_sd.h new file mode 100755 index 00000000..bc3151b7 --- /dev/null +++ b/src/lib/id_sd.h @@ -0,0 +1,262 @@ +/* Project 16 Source Code~ + * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover + * + * This file is part of Project 16. + * + * Project 16 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Project 16 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +// +// ID Engine +// ID_SD.h - Sound Manager Header +// Version for Wolfenstein +// By Jason Blochowiak +// + +#ifndef __16_SD__ +#define __16_SD__ + +#include "src/lib/16_head.h" +#include "src/lib/16_pm.h" + +void alOut(byte n,byte b); + +#ifdef __DEBUG__ +#define __DEBUG_SoundMgr__ +#endif + +#define TickBase 70 // 70Hz per tick - used as a base for timer 0 + +typedef enum { + sdm_Off, + sdm_PC,sdm_AdLib, + } SDMode; +typedef enum { + smm_Off,smm_AdLib + } SMMode; +typedef enum { + sds_Off,sds_PC,sds_SoundSource,sds_SoundBlaster + } SDSMode; +typedef struct + { + dword length; + word priority; + } SoundCommon; + +// PC Sound stuff +#define pcTimer 0x42 +#define pcTAccess 0x43 +#define pcSpeaker 0x61 + +#define pcSpkBits 3 + +typedef struct + { + SoundCommon common; + byte data[1]; + } PCSound; + +// Registers for the Sound Blaster card - needs to be offset by n0 (0x10,0x20,0x30,0x40,0x50,0x60) +#define sbReset 0x206 // W +#define sbFMStatus 0x208 // R +#define sbFMAddr 0x208 // W +#define sbFMData 0x209 // W +#define sbReadData 0x20a // R +#define sbWriteCmd 0x20c // W +#define sbWriteData 0x20c // W +#define sbWriteStat 0x20c // R +#define sbDataAvail 0x20e // R + +// Registers for the Sound Blaster Pro card - needs to be offset by n0 (0x20 or 0x40) +#define sbpLFMStatus 0x200 // R +#define sbpLFMAddr 0x200 // W +#define sbpLFMData 0x201 // W +#define sbpRFMStatus 0x202 // R +#define sbpRFMAddr 0x202 // W +#define sbpRFMData 0x203 // W +#define sbpMixerAddr 0x204 // W +#define sbpMixerData 0x205 // RW +#define sbpCDData 0x210 // R +#define sbpCDCommand 0x210 // W +#define sbpCDStatus 0x211 // R +#define sbpCDReset 0x212 // W + +// SBPro Mixer addresses +#define sbpmReset 0x00 +#define sbpmVoiceVol 0x04 +#define sbpmMicMix 0x0a +#define sbpmFilterADC 0x0c +#define sbpmControl 0x0e +#define sbpmMasterVol 0x22 +#define sbpmFMVol 0x26 +#define sbpmCDVol 0x28 +#define sbpmLineVol 0x2e + +typedef struct + { + SoundCommon common; + word hertz; + byte bits, + reference, + data[1]; + } SampledSound; + +// Registers for the AdLib card +#define alFMStatus 0x388 // R +#define alFMAddr 0x388 // W +#define alFMData 0x389 // W + +// Register addresses +// Operator stuff +#define alChar 0x20 +#define alScale 0x40 +#define alAttack 0x60 +#define alSus 0x80 +#define alWave 0xe0 +// Channel stuff +#define alFreqL 0xa0 +#define alFreqH 0xb0 +#define alFeedCon 0xc0 +// Global stuff +#define alEffects 0xbd + +typedef struct + { + byte mChar,cChar, + mScale,cScale, + mAttack,cAttack, + mSus,cSus, + mWave,cWave, + nConn, + + // These are only for Muse - these bytes are really unused + voice, + mode, + unused[3]; + } Instrument; + +typedef struct + { + SoundCommon common; + Instrument inst; + byte block, + data[1]; + } AdLibSound; + +// +// Sequencing stuff +// +#define sqMaxTracks 10 +#define sqMaxMoods 1 // DEBUG + +#define sev_Null 0 // Does nothing +#define sev_NoteOff 1 // Turns a note off +#define sev_NoteOn 2 // Turns a note on +#define sev_NotePitch 3 // Sets the pitch of a currently playing note +#define sev_NewInst 4 // Installs a new instrument +#define sev_NewPerc 5 // Installs a new percussive instrument +#define sev_PercOn 6 // Turns a percussive note on +#define sev_PercOff 7 // Turns a percussive note off +#define sev_SeqEnd -1 // Terminates a sequence + +// Flags for MusicGroup.flags +#define sf_Melodic 0 +#define sf_Percussive 1 + +#if 1 +typedef struct + { + word length, + values[1]; + } MusicGroup; +#else +typedef struct + { + word flags, + count, + offsets[1]; + } MusicGroup; +#endif + +typedef struct + { + /* This part needs to be set up by the user */ + word mood,far *moods[sqMaxMoods]; + + /* The rest is set up by the code */ + Instrument inst; + boolean percussive; + word far *seq; + dword nextevent; + } ActiveTrack; + +#define sqmode_Normal 0 +#define sqmode_FadeIn 1 +#define sqmode_FadeOut 2 + +#define sqMaxFade 64 // DEBUG + + +// Global variables +extern boolean AdLibPresent, + SoundSourcePresent, + SoundBlasterPresent, + NeedsMusic, // For Caching Mgr + SoundPositioned; +extern SDMode SoundMode; +extern SDSMode DigiMode; +extern SMMode MusicMode; +extern boolean DigiPlaying; +extern int DigiMap[]; +extern dword TimeCount; // Global time in ticks + +// Function prototypes +extern void SD_Startup(void), + SD_Shutdown(void), + SD_Default(boolean gotit,SDMode sd,SMMode sm), + + SD_PositionSound(int leftvol,int rightvol); +extern boolean SD_PlaySound(soundnames sound); +extern void SD_SetPosition(int leftvol,int rightvol), + SD_StopSound(void), + SD_WaitSoundDone(void), + + SD_StartMusic(MusicGroup far *music), + SD_MusicOn(void), + SD_MusicOff(void), + SD_FadeOutMusic(void), + + SD_SetUserHook(void (*hook)(void)); +extern boolean SD_MusicPlaying(void), + SD_SetSoundMode(SDMode mode), + SD_SetMusicMode(SMMode mode); +extern word SD_SoundPlaying(void); + +extern void SD_SetDigiDevice(SDSMode), + SD_PlayDigitized(word which,int leftpos,int rightpos), + SD_StopDigitized(void), + SD_Poll(void); + +#ifdef _MUSE_ // MUSE Goes directly to the lower level routines +extern void SDL_PCPlaySound(PCSound far *sound), + SDL_PCStopSound(void), + SDL_ALPlaySound(AdLibSound far *sound), + SDL_ALStopSound(void); +#endif + +#endif + diff --git a/simulate-sparky4-watcom-env.sh b/src/util/shbat/simulate-sparky4-watcom-env.sh old mode 100644 new mode 100755 similarity index 100% rename from simulate-sparky4-watcom-env.sh rename to src/util/shbat/simulate-sparky4-watcom-env.sh