diff options
Diffstat (limited to 'WinQuake/snd_dos.c')
| -rw-r--r-- | WinQuake/snd_dos.c | 1306 |
1 files changed, 653 insertions, 653 deletions
diff --git a/WinQuake/snd_dos.c b/WinQuake/snd_dos.c index bcb93b2..a0445cd 100644 --- a/WinQuake/snd_dos.c +++ b/WinQuake/snd_dos.c @@ -1,653 +1,653 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "quakedef.h" -#include "dosisms.h" - -int BLASTER_GetDMAPos(void); - -/* -=============================================================================== -GUS SUPPORT - -=============================================================================== -*/ - -qboolean GUS_Init (void); -int GUS_GetDMAPos (void); -void GUS_Shutdown (void); - - -/* -=============================================================================== - -BLASTER SUPPORT - -=============================================================================== -*/ - -short *dma_buffer=0; -static int dma_size; -static int dma; - -static int dsp_port; -static int irq; -static int low_dma; -static int high_dma; -static int mixer_port; -static int mpu401_port; - -int dsp_version; -int dsp_minor_version; - -int timeconstant=-1; - - -void PrintBits (byte b) -{ - int i; - char str[9]; - - for (i=0 ; i<8 ; i++) - str[i] = '0' + ((b & (1<<(7-i))) > 0); - - str[8] = 0; - Con_Printf ("%s (%i)", str, b); -} - -void SB_Info_f(void) -{ - Con_Printf ("BLASTER=%s\n", getenv("BLASTER")); - Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version); - Con_Printf("dma=%d\n", dma); - if (timeconstant != -1) - Con_Printf("timeconstant=%d\n", timeconstant); - Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ()); -} - -// ======================================================================= -// Interprets BLASTER variable -// ======================================================================= - -int GetBLASTER(void) -{ - char *BLASTER; - char *param; - - BLASTER = getenv("BLASTER"); - if (!BLASTER) - return 0; - - param = strchr(BLASTER, 'A'); - if (!param) - param = strchr(BLASTER, 'a'); - if (!param) - return 0; - sscanf(param+1, "%x", &dsp_port); - - param = strchr(BLASTER, 'I'); - if (!param) - param = strchr(BLASTER, 'i'); - if (!param) - return 0; - sscanf(param+1, "%d", &irq); - - param = strchr(BLASTER, 'D'); - if (!param) - param = strchr(BLASTER, 'd'); - if (!param) - return 0; - sscanf(param+1, "%d", &low_dma); - - param = strchr(BLASTER, 'H'); - if (!param) - param = strchr(BLASTER, 'h'); - if (param) - sscanf(param+1, "%d", &high_dma); - - param = strchr(BLASTER, 'M'); - if (!param) - param = strchr(BLASTER, 'm'); - if (param) - sscanf(param+1, "%x", &mixer_port); - else - mixer_port = dsp_port; - - param = strchr(BLASTER, 'P'); - if (!param) - param = strchr(BLASTER, 'p'); - if (param) - sscanf(param+1, "%x", &mpu401_port); - - return 1; - -} - -// ================================================================== -// Resets DSP. Returns 0 on success. -// ================================================================== - -int ResetDSP(void) -{ - volatile int i; - - dos_outportb(dsp_port + 6, 1); - for (i=65536 ; i ; i--) ; - dos_outportb(dsp_port + 6, 0); - for (i=65536 ; i ; i--) - { - if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue; - if (dos_inportb(dsp_port + 0xa) == 0xaa) break; - } - if (i) return 0; - else return 1; - -} - -int ReadDSP(void) -{ - while (!(dos_inportb(dsp_port+0xe)&0x80)) ; - return dos_inportb(dsp_port+0xa); -} - -void WriteDSP(int val) -{ - while ((dos_inportb(dsp_port+0xc)&0x80)) ; - dos_outportb(dsp_port+0xc, val); -} - -int ReadMixer(int addr) -{ - dos_outportb(mixer_port+4, addr); - return dos_inportb(mixer_port+5); -} - -void WriteMixer(int addr, int val) -{ - dos_outportb(mixer_port+4, addr); - dos_outportb(mixer_port+5, val); -} - -int oldmixervalue; - -/* -================ -StartSB - -================ -*/ -void StartSB(void) -{ - int i; - -// version 4.xx startup code - if (dsp_version >= 4) - { - Con_Printf("Version 4 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - WriteDSP(0x41); - - WriteDSP(shm->speed>>8); - WriteDSP(shm->speed&0xff); - - WriteDSP(0xb6); // 16-bit output - WriteDSP(0x30); // stereo - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - } -// version 3.xx startup code - else if (dsp_version == 3) - { - Con_Printf("Version 3 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - oldmixervalue = ReadMixer (0xe); - WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo - - WriteDSP(0x14); // send one byte - WriteDSP(0x0); - WriteDSP(0x0); - - for (i=0 ; i<0x10000 ; i++) - dos_inportb(dsp_port+0xe); // ack the dsp - - timeconstant = 65536-(256000000/(shm->channels*shm->speed)); - WriteDSP(0x40); - WriteDSP(timeconstant>>8); - - WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter - - WriteDSP(0x48); - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - - WriteDSP(0x90); // high speed 8 bit stereo - } -// normal speed mono - else - { - Con_Printf("Version 2 SB startup\n"); - WriteDSP(0xd1); // turn on speaker - - timeconstant = 65536-(256000000/(shm->channels*shm->speed)); - WriteDSP(0x40); - WriteDSP(timeconstant>>8); - - WriteDSP(0x48); - WriteDSP((shm->samples-1) & 0xff); // # of samples - 1 - WriteDSP((shm->samples-1) >> 8); - - WriteDSP(0x1c); // normal speed 8 bit mono - } -} - -static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; -static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc }; -static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce }; - -static int mode_reg; -static int flipflop_reg; -static int disable_reg; -static int clear_reg; - -/* -================ -StartDMA - -================ -*/ -void StartDMA(void) -{ - int mode; - int realaddr; - - realaddr = ptr2real(dma_buffer); - -// use a high dma channel if specified - if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma - dma = high_dma; - else - dma = low_dma; - - Con_Printf ("Using DMA channel %i\n", dma); - - if (dma > 3) - { - mode_reg = 0xd6; - flipflop_reg = 0xd8; - disable_reg = 0xd4; - clear_reg = 0xdc; - } - else - { - mode_reg = 0xb; - flipflop_reg = 0xc; - disable_reg = 0xa; - clear_reg = 0xe; - } - - dos_outportb(disable_reg, dma|4); // disable channel - // set mode- see "undocumented pc", p.876 - mode = (1<<6) // single-cycle - +(0<<5) // address increment - +(1<<4) // auto-init dma - +(2<<2) // read - +(dma&3); // channel # - dos_outportb(mode_reg, mode); - -// set address - // set page - dos_outportb(page_reg[dma], realaddr >> 16); - - if (dma > 3) - { // address is in words - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff); - dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff); - - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff); - dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8); - } - else - { // address is in bytes - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(addr_reg[dma], realaddr & 0xff); - dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff); - - dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value - dos_outportb(count_reg[dma], (dma_size-1) & 0xff); - dos_outportb(count_reg[dma], (dma_size-1) >> 8); - } - - dos_outportb(clear_reg, 0); // clear write mask - dos_outportb(disable_reg, dma&~4); -} - - -/* -================== -BLASTER_Init - -Returns false if nothing is found. -================== -*/ -qboolean BLASTER_Init(void) -{ - int size; - int realaddr; - int rc; - int p; - - shm = 0; - rc = 0; - -// -// must have a blaster variable set -// - if (!GetBLASTER()) - { - Con_NotifyBox ( - "The BLASTER environment variable\n" - "is not set, sound effects are\n" - "disabled. See README.TXT for help.\n" - ); - return 0; - } - - if (ResetDSP()) - { - Con_Printf("Could not reset SB"); - return 0; - } - -// -// get dsp version -// - WriteDSP(0xe1); - dsp_version = ReadDSP(); - dsp_minor_version = ReadDSP(); - -// we need at least v2 for auto-init dma - if (dsp_version < 2) - { - Con_Printf ("Sound blaster must be at least v2.0\n"); - return 0; - } - -// allow command line parm to set quality down - p = COM_CheckParm ("-dsp"); - if (p && p < com_argc - 1) - { - p = Q_atoi (com_argv[p+1]); - if (p < 2 || p > 4) - Con_Printf ("-dsp parameter can only be 2, 3, or 4\n"); - else if (p > dsp_version) - Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version); - else - dsp_version = p; - } - - -// everyone does 11khz sampling rate unless told otherwise - shm = &sn; - shm->speed = 11025; - rc = COM_CheckParm("-sspeed"); - if (rc) - shm->speed = Q_atoi(com_argv[rc+1]); - -// version 4 cards (sb 16) do 16 bit stereo - if (dsp_version >= 4) - { - shm->channels = 2; - shm->samplebits = 16; - } -// version 3 cards (sb pro) do 8 bit stereo - else if (dsp_version == 3) - { - shm->channels = 2; - shm->samplebits = 8; - } -// v2 cards do 8 bit mono - else - { - shm->channels = 1; - shm->samplebits = 8; - } - - - Cmd_AddCommand("sbinfo", SB_Info_f); - size = 4096; - -// allocate 8k and get a 4k-aligned buffer from it - dma_buffer = dos_getmemory(size*2); - if (!dma_buffer) - { - Con_Printf("Couldn't allocate sound dma buffer"); - return false; - } - - realaddr = ptr2real(dma_buffer); - realaddr = (realaddr + size) & ~(size-1); - dma_buffer = (short *) real2ptr(realaddr); - dma_size = size; - - memset(dma_buffer, 0, dma_size); - - shm->soundalive = true; - shm->splitbuffer = false; - - shm->samples = size/(shm->samplebits/8); - shm->samplepos = 0; - shm->submission_chunk = 1; - shm->buffer = (unsigned char *) dma_buffer; - shm->samples = size/(shm->samplebits/8); - - StartDMA(); - StartSB(); - - return true; -} - - -/* -============== -BLASTER_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int BLASTER_GetDMAPos(void) -{ - int count; - -// this function is called often. acknowledge the transfer completions -// all the time so that it loops - if (dsp_version >= 4) - dos_inportb(dsp_port+0xf); // 16 bit audio - else - dos_inportb(dsp_port+0xe); // 8 bit audio - -// clear 16-bit reg flip-flop -// load the current dma count register - if (dma < 4) - { - dos_outportb(0xc, 0); - count = dos_inportb(dma*2+1); - count += dos_inportb(dma*2+1) << 8; - if (shm->samplebits == 16) - count /= 2; - count = shm->samples - (count+1); - } - else - { - dos_outportb(0xd8, 0); - count = dos_inportb(0xc0+(dma-4)*4+2); - count += dos_inportb(0xc0+(dma-4)*4+2) << 8; - if (shm->samplebits == 8) - count *= 2; - count = shm->samples - (count+1); - } - -// Con_Printf("DMA pos = 0x%x\n", count); - - shm->samplepos = count & (shm->samples-1); - return shm->samplepos; - -} - -/* -============== -BLASTER_Shutdown - -Reset the sound device for exiting -=============== -*/ -void BLASTER_Shutdown(void) -{ - if (dsp_version >= 4) - { - } - else if (dsp_version == 3) - { - ResetDSP (); // stop high speed mode - WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on - } - else - { - - } - - WriteDSP(0xd3); // turn off speaker - ResetDSP (); - - dos_outportb(disable_reg, dma|4); // disable dma channel -} - - - -/* -=============================================================================== - -INTERFACE - -=============================================================================== -*/ - -typedef enum -{ - dma_none, - dma_blaster, - dma_gus -} dmacard_t; - -dmacard_t dmacard; - -/* -================== -SNDDM_Init - -Try to find a sound device to mix for. -Returns false if nothing is found. -Returns true and fills in the "shm" structure with information for the mixer. -================== -*/ -qboolean SNDDMA_Init(void) -{ - if (GUS_Init ()) - { - dmacard = dma_gus; - return true; - } - if (BLASTER_Init ()) - { - dmacard = dma_blaster; - return true; - } - - dmacard = dma_none; - - return false; -} - - -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples, not stereo) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos(void) -{ - switch (dmacard) - { - case dma_blaster: - return BLASTER_GetDMAPos (); - case dma_gus: - return GUS_GetDMAPos (); - case dma_none: - break; - } - - return 0; -} - -/* -============== -SNDDMA_Shutdown - -Reset the sound device for exiting -=============== -*/ -void SNDDMA_Shutdown(void) -{ - switch (dmacard) - { - case dma_blaster: - BLASTER_Shutdown (); - break; - case dma_gus: - GUS_Shutdown (); - break; - case dma_none: - break; - } - - dmacard = dma_none; - return; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -=============== -*/ -void SNDDMA_Submit(void) -{ -} - +/*
+Copyright (C) 1996-1997 Id Software, Inc.
+
+This program 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 2
+of the License, or (at your option) any later version.
+
+This program 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, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "quakedef.h"
+#include "dosisms.h"
+
+int BLASTER_GetDMAPos(void);
+
+/*
+===============================================================================
+GUS SUPPORT
+
+===============================================================================
+*/
+
+qboolean GUS_Init (void);
+int GUS_GetDMAPos (void);
+void GUS_Shutdown (void);
+
+
+/*
+===============================================================================
+
+BLASTER SUPPORT
+
+===============================================================================
+*/
+
+short *dma_buffer=0;
+static int dma_size;
+static int dma;
+
+static int dsp_port;
+static int irq;
+static int low_dma;
+static int high_dma;
+static int mixer_port;
+static int mpu401_port;
+
+int dsp_version;
+int dsp_minor_version;
+
+int timeconstant=-1;
+
+
+void PrintBits (byte b)
+{
+ int i;
+ char str[9];
+
+ for (i=0 ; i<8 ; i++)
+ str[i] = '0' + ((b & (1<<(7-i))) > 0);
+
+ str[8] = 0;
+ Con_Printf ("%s (%i)", str, b);
+}
+
+void SB_Info_f(void)
+{
+ Con_Printf ("BLASTER=%s\n", getenv("BLASTER"));
+ Con_Printf("dsp version=%d.%d\n", dsp_version, dsp_minor_version);
+ Con_Printf("dma=%d\n", dma);
+ if (timeconstant != -1)
+ Con_Printf("timeconstant=%d\n", timeconstant);
+ Con_Printf("dma position:%i\n", BLASTER_GetDMAPos ());
+}
+
+// =======================================================================
+// Interprets BLASTER variable
+// =======================================================================
+
+int GetBLASTER(void)
+{
+ char *BLASTER;
+ char *param;
+
+ BLASTER = getenv("BLASTER");
+ if (!BLASTER)
+ return 0;
+
+ param = strchr(BLASTER, 'A');
+ if (!param)
+ param = strchr(BLASTER, 'a');
+ if (!param)
+ return 0;
+ sscanf(param+1, "%x", &dsp_port);
+
+ param = strchr(BLASTER, 'I');
+ if (!param)
+ param = strchr(BLASTER, 'i');
+ if (!param)
+ return 0;
+ sscanf(param+1, "%d", &irq);
+
+ param = strchr(BLASTER, 'D');
+ if (!param)
+ param = strchr(BLASTER, 'd');
+ if (!param)
+ return 0;
+ sscanf(param+1, "%d", &low_dma);
+
+ param = strchr(BLASTER, 'H');
+ if (!param)
+ param = strchr(BLASTER, 'h');
+ if (param)
+ sscanf(param+1, "%d", &high_dma);
+
+ param = strchr(BLASTER, 'M');
+ if (!param)
+ param = strchr(BLASTER, 'm');
+ if (param)
+ sscanf(param+1, "%x", &mixer_port);
+ else
+ mixer_port = dsp_port;
+
+ param = strchr(BLASTER, 'P');
+ if (!param)
+ param = strchr(BLASTER, 'p');
+ if (param)
+ sscanf(param+1, "%x", &mpu401_port);
+
+ return 1;
+
+}
+
+// ==================================================================
+// Resets DSP. Returns 0 on success.
+// ==================================================================
+
+int ResetDSP(void)
+{
+ volatile int i;
+
+ dos_outportb(dsp_port + 6, 1);
+ for (i=65536 ; i ; i--) ;
+ dos_outportb(dsp_port + 6, 0);
+ for (i=65536 ; i ; i--)
+ {
+ if (!(dos_inportb(dsp_port + 0xe) & 0x80)) continue;
+ if (dos_inportb(dsp_port + 0xa) == 0xaa) break;
+ }
+ if (i) return 0;
+ else return 1;
+
+}
+
+int ReadDSP(void)
+{
+ while (!(dos_inportb(dsp_port+0xe)&0x80)) ;
+ return dos_inportb(dsp_port+0xa);
+}
+
+void WriteDSP(int val)
+{
+ while ((dos_inportb(dsp_port+0xc)&0x80)) ;
+ dos_outportb(dsp_port+0xc, val);
+}
+
+int ReadMixer(int addr)
+{
+ dos_outportb(mixer_port+4, addr);
+ return dos_inportb(mixer_port+5);
+}
+
+void WriteMixer(int addr, int val)
+{
+ dos_outportb(mixer_port+4, addr);
+ dos_outportb(mixer_port+5, val);
+}
+
+int oldmixervalue;
+
+/*
+================
+StartSB
+
+================
+*/
+void StartSB(void)
+{
+ int i;
+
+// version 4.xx startup code
+ if (dsp_version >= 4)
+ {
+ Con_Printf("Version 4 SB startup\n");
+ WriteDSP(0xd1); // turn on speaker
+
+ WriteDSP(0x41);
+
+ WriteDSP(shm->speed>>8);
+ WriteDSP(shm->speed&0xff);
+
+ WriteDSP(0xb6); // 16-bit output
+ WriteDSP(0x30); // stereo
+ WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
+ WriteDSP((shm->samples-1) >> 8);
+ }
+// version 3.xx startup code
+ else if (dsp_version == 3)
+ {
+ Con_Printf("Version 3 SB startup\n");
+ WriteDSP(0xd1); // turn on speaker
+
+ oldmixervalue = ReadMixer (0xe);
+ WriteMixer (0xe, oldmixervalue | 0x2);// turn on stereo
+
+ WriteDSP(0x14); // send one byte
+ WriteDSP(0x0);
+ WriteDSP(0x0);
+
+ for (i=0 ; i<0x10000 ; i++)
+ dos_inportb(dsp_port+0xe); // ack the dsp
+
+ timeconstant = 65536-(256000000/(shm->channels*shm->speed));
+ WriteDSP(0x40);
+ WriteDSP(timeconstant>>8);
+
+ WriteMixer (0xe, ReadMixer(0xe) | 0x20);// turn off filter
+
+ WriteDSP(0x48);
+ WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
+ WriteDSP((shm->samples-1) >> 8);
+
+ WriteDSP(0x90); // high speed 8 bit stereo
+ }
+// normal speed mono
+ else
+ {
+ Con_Printf("Version 2 SB startup\n");
+ WriteDSP(0xd1); // turn on speaker
+
+ timeconstant = 65536-(256000000/(shm->channels*shm->speed));
+ WriteDSP(0x40);
+ WriteDSP(timeconstant>>8);
+
+ WriteDSP(0x48);
+ WriteDSP((shm->samples-1) & 0xff); // # of samples - 1
+ WriteDSP((shm->samples-1) >> 8);
+
+ WriteDSP(0x1c); // normal speed 8 bit mono
+ }
+}
+
+static int page_reg[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
+static int addr_reg[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
+static int count_reg[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };
+
+static int mode_reg;
+static int flipflop_reg;
+static int disable_reg;
+static int clear_reg;
+
+/*
+================
+StartDMA
+
+================
+*/
+void StartDMA(void)
+{
+ int mode;
+ int realaddr;
+
+ realaddr = ptr2real(dma_buffer);
+
+// use a high dma channel if specified
+ if (high_dma && dsp_version >= 4) // 8 bit snd can never use 16 bit dma
+ dma = high_dma;
+ else
+ dma = low_dma;
+
+ Con_Printf ("Using DMA channel %i\n", dma);
+
+ if (dma > 3)
+ {
+ mode_reg = 0xd6;
+ flipflop_reg = 0xd8;
+ disable_reg = 0xd4;
+ clear_reg = 0xdc;
+ }
+ else
+ {
+ mode_reg = 0xb;
+ flipflop_reg = 0xc;
+ disable_reg = 0xa;
+ clear_reg = 0xe;
+ }
+
+ dos_outportb(disable_reg, dma|4); // disable channel
+ // set mode- see "undocumented pc", p.876
+ mode = (1<<6) // single-cycle
+ +(0<<5) // address increment
+ +(1<<4) // auto-init dma
+ +(2<<2) // read
+ +(dma&3); // channel #
+ dos_outportb(mode_reg, mode);
+
+// set address
+ // set page
+ dos_outportb(page_reg[dma], realaddr >> 16);
+
+ if (dma > 3)
+ { // address is in words
+ dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
+ dos_outportb(addr_reg[dma], (realaddr>>1) & 0xff);
+ dos_outportb(addr_reg[dma], (realaddr>>9) & 0xff);
+
+ dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
+ dos_outportb(count_reg[dma], ((dma_size>>1)-1) & 0xff);
+ dos_outportb(count_reg[dma], ((dma_size>>1)-1) >> 8);
+ }
+ else
+ { // address is in bytes
+ dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
+ dos_outportb(addr_reg[dma], realaddr & 0xff);
+ dos_outportb(addr_reg[dma], (realaddr>>8) & 0xff);
+
+ dos_outportb(flipflop_reg, 0); // prepare to send 16-bit value
+ dos_outportb(count_reg[dma], (dma_size-1) & 0xff);
+ dos_outportb(count_reg[dma], (dma_size-1) >> 8);
+ }
+
+ dos_outportb(clear_reg, 0); // clear write mask
+ dos_outportb(disable_reg, dma&~4);
+}
+
+
+/*
+==================
+BLASTER_Init
+
+Returns false if nothing is found.
+==================
+*/
+qboolean BLASTER_Init(void)
+{
+ int size;
+ int realaddr;
+ int rc;
+ int p;
+
+ shm = 0;
+ rc = 0;
+
+//
+// must have a blaster variable set
+//
+ if (!GetBLASTER())
+ {
+ Con_NotifyBox (
+ "The BLASTER environment variable\n"
+ "is not set, sound effects are\n"
+ "disabled. See README.TXT for help.\n"
+ );
+ return 0;
+ }
+
+ if (ResetDSP())
+ {
+ Con_Printf("Could not reset SB");
+ return 0;
+ }
+
+//
+// get dsp version
+//
+ WriteDSP(0xe1);
+ dsp_version = ReadDSP();
+ dsp_minor_version = ReadDSP();
+
+// we need at least v2 for auto-init dma
+ if (dsp_version < 2)
+ {
+ Con_Printf ("Sound blaster must be at least v2.0\n");
+ return 0;
+ }
+
+// allow command line parm to set quality down
+ p = COM_CheckParm ("-dsp");
+ if (p && p < com_argc - 1)
+ {
+ p = Q_atoi (com_argv[p+1]);
+ if (p < 2 || p > 4)
+ Con_Printf ("-dsp parameter can only be 2, 3, or 4\n");
+ else if (p > dsp_version)
+ Con_Printf ("Can't -dsp %i on v%i hardware\n", p, dsp_version);
+ else
+ dsp_version = p;
+ }
+
+
+// everyone does 11khz sampling rate unless told otherwise
+ shm = &sn;
+ shm->speed = 11025;
+ rc = COM_CheckParm("-sspeed");
+ if (rc)
+ shm->speed = Q_atoi(com_argv[rc+1]);
+
+// version 4 cards (sb 16) do 16 bit stereo
+ if (dsp_version >= 4)
+ {
+ shm->channels = 2;
+ shm->samplebits = 16;
+ }
+// version 3 cards (sb pro) do 8 bit stereo
+ else if (dsp_version == 3)
+ {
+ shm->channels = 2;
+ shm->samplebits = 8;
+ }
+// v2 cards do 8 bit mono
+ else
+ {
+ shm->channels = 1;
+ shm->samplebits = 8;
+ }
+
+
+ Cmd_AddCommand("sbinfo", SB_Info_f);
+ size = 4096;
+
+// allocate 8k and get a 4k-aligned buffer from it
+ dma_buffer = dos_getmemory(size*2);
+ if (!dma_buffer)
+ {
+ Con_Printf("Couldn't allocate sound dma buffer");
+ return false;
+ }
+
+ realaddr = ptr2real(dma_buffer);
+ realaddr = (realaddr + size) & ~(size-1);
+ dma_buffer = (short *) real2ptr(realaddr);
+ dma_size = size;
+
+ memset(dma_buffer, 0, dma_size);
+
+ shm->soundalive = true;
+ shm->splitbuffer = false;
+
+ shm->samples = size/(shm->samplebits/8);
+ shm->samplepos = 0;
+ shm->submission_chunk = 1;
+ shm->buffer = (unsigned char *) dma_buffer;
+ shm->samples = size/(shm->samplebits/8);
+
+ StartDMA();
+ StartSB();
+
+ return true;
+}
+
+
+/*
+==============
+BLASTER_GetDMAPos
+
+return the current sample position (in mono samples read)
+inside the recirculating dma buffer, so the mixing code will know
+how many sample are required to fill it up.
+===============
+*/
+int BLASTER_GetDMAPos(void)
+{
+ int count;
+
+// this function is called often. acknowledge the transfer completions
+// all the time so that it loops
+ if (dsp_version >= 4)
+ dos_inportb(dsp_port+0xf); // 16 bit audio
+ else
+ dos_inportb(dsp_port+0xe); // 8 bit audio
+
+// clear 16-bit reg flip-flop
+// load the current dma count register
+ if (dma < 4)
+ {
+ dos_outportb(0xc, 0);
+ count = dos_inportb(dma*2+1);
+ count += dos_inportb(dma*2+1) << 8;
+ if (shm->samplebits == 16)
+ count /= 2;
+ count = shm->samples - (count+1);
+ }
+ else
+ {
+ dos_outportb(0xd8, 0);
+ count = dos_inportb(0xc0+(dma-4)*4+2);
+ count += dos_inportb(0xc0+(dma-4)*4+2) << 8;
+ if (shm->samplebits == 8)
+ count *= 2;
+ count = shm->samples - (count+1);
+ }
+
+// Con_Printf("DMA pos = 0x%x\n", count);
+
+ shm->samplepos = count & (shm->samples-1);
+ return shm->samplepos;
+
+}
+
+/*
+==============
+BLASTER_Shutdown
+
+Reset the sound device for exiting
+===============
+*/
+void BLASTER_Shutdown(void)
+{
+ if (dsp_version >= 4)
+ {
+ }
+ else if (dsp_version == 3)
+ {
+ ResetDSP (); // stop high speed mode
+ WriteMixer (0xe, oldmixervalue); // turn stereo off and filter on
+ }
+ else
+ {
+
+ }
+
+ WriteDSP(0xd3); // turn off speaker
+ ResetDSP ();
+
+ dos_outportb(disable_reg, dma|4); // disable dma channel
+}
+
+
+
+/*
+===============================================================================
+
+INTERFACE
+
+===============================================================================
+*/
+
+typedef enum
+{
+ dma_none,
+ dma_blaster,
+ dma_gus
+} dmacard_t;
+
+dmacard_t dmacard;
+
+/*
+==================
+SNDDM_Init
+
+Try to find a sound device to mix for.
+Returns false if nothing is found.
+Returns true and fills in the "shm" structure with information for the mixer.
+==================
+*/
+qboolean SNDDMA_Init(void)
+{
+ if (GUS_Init ())
+ {
+ dmacard = dma_gus;
+ return true;
+ }
+ if (BLASTER_Init ())
+ {
+ dmacard = dma_blaster;
+ return true;
+ }
+
+ dmacard = dma_none;
+
+ return false;
+}
+
+
+/*
+==============
+SNDDMA_GetDMAPos
+
+return the current sample position (in mono samples, not stereo)
+inside the recirculating dma buffer, so the mixing code will know
+how many sample are required to fill it up.
+===============
+*/
+int SNDDMA_GetDMAPos(void)
+{
+ switch (dmacard)
+ {
+ case dma_blaster:
+ return BLASTER_GetDMAPos ();
+ case dma_gus:
+ return GUS_GetDMAPos ();
+ case dma_none:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+==============
+SNDDMA_Shutdown
+
+Reset the sound device for exiting
+===============
+*/
+void SNDDMA_Shutdown(void)
+{
+ switch (dmacard)
+ {
+ case dma_blaster:
+ BLASTER_Shutdown ();
+ break;
+ case dma_gus:
+ GUS_Shutdown ();
+ break;
+ case dma_none:
+ break;
+ }
+
+ dmacard = dma_none;
+ return;
+}
+
+/*
+==============
+SNDDMA_Submit
+
+Send sound to device if buffer isn't really the dma buffer
+===============
+*/
+void SNDDMA_Submit(void)
+{
+}
+
|
