From a8f828a066773a59fdf646299359d35ae0e845af Mon Sep 17 00:00:00 2001 From: wyatt8740 Date: Mon, 6 Jan 2014 12:02:16 -0500 Subject: Removed accidental upload of copyrighted map files --- WinQuake/snd_dos.c | 1306 ++++++++++++++++++++++++++-------------------------- 1 file changed, 653 insertions(+), 653 deletions(-) (limited to 'WinQuake/snd_dos.c') 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) +{ +} + -- cgit v1.2.3