⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snd_gus.c

📁 quake1 dos源代码最新版本
💻 C
📖 第 1 页 / 共 3 页
字号:
            get_field_string(s,ts);
            break;
         }
         // If we reach the end of the section, start over
         if (feof(f) || is_section(ts,"*"))
            fseek(f,section_buffers[current_section].offset,SEEK_SET);
         if (ftell(f)==start_pos)
            return;
      }
   }
}

//=============================================================================

#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long

#define BUFFER_SIZE 4096

#define CODEC_ADC_INPUT_CONTROL_LEFT	0x00
#define CODEC_ADC_INPUT_CONTROL_RIGHT	0x01
#define CODEC_AUX1_INPUT_CONTROL_LEFT	0x02
#define CODEC_AUX1_INPUT_CONTROL_RIGHT	0x03
#define CODEC_AUX2_INPUT_CONTROL_LEFT	0x04
#define CODEC_AUX2_INPUT_CONTROL_RIGHT	0x05
#define CODEC_DAC_OUTPUT_CONTROL_LEFT	0x06
#define CODEC_DAC_OUTPUT_CONTROL_RIGHT	0x07
#define CODEC_FS_FORMAT			0x08
#define CODEC_INTERFACE_CONFIG		0x09
#define CODEC_PIN_CONTROL		0x0A
#define CODEC_ERROR_STATUS_AND_INIT	0x0B
#define CODEC_MODE_AND_ID		0x0C
#define CODEC_LOOPBACK_CONTROL		0x0D
#define CODEC_PLAYBACK_UPPER_BASE_COUNT	0x0E
#define CODEC_PLAYBACK_LOWER_BASE_COUNT	0x0F

#define SET_CONTROL			0x00
#define SET_FREQUENCY			0x01
#define SET_START_HIGH			0x02
#define SET_START_LOW			0x03
#define SET_END_HIGH			0x04
#define SET_END_LOW			0x05
#define SET_VOLUME_RATE			0x06
#define SET_VOLUME_START		0x07
#define SET_VOLUME_END			0x08
#define SET_CURR_VOLUME			0x09
#define SET_VOLUME			0x09
#define SET_ACC_HIGH			0x0A
#define SET_ACC_LOW			0x0B
#define SET_BALANCE			0x0C
#define SET_VOLUME_CONTROL		0x0D
#define SET_VOICES			0x0E

#define DMA_CONTROL			0x41
#define SET_DMA_ADDRESS			0x42
#define SET_DRAM_LOW			0x43
#define SET_DRAM_HIGH			0x44
#define ADLIB_CONTROL			0x45
#define ADLIB_TIMER1			0x46
#define ADLIB_TIMER2			0x47
#define SET_RECORD_RATE			0x48
#define RECORD_CONTROL			0x49
#define SET_JOYSTICK			0x4B
#define MASTER_RESET			0x4C

#define GET_CONTROL			0x80
#define GET_FREQUENCY			0x81
#define GET_START_HIGH			0x82
#define GET_START_LOW			0x83
#define GET_END_HIGH			0x84
#define GET_END_LOW			0x85
#define GET_VOLUME_RATE			0x86
#define GET_VOLUME_START		0x87
#define GET_VOLUME_END			0x88
#define GET_VOLUME			0x89
#define GET_ACC_HIGH			0x8A
#define GET_ACC_LOW			0x8B
#define GET_BALANCE			0x8C
#define GET_VOLUME_CONTROL		0x8D
#define GET_VOICES			0x8E
#define GET_IRQV                        0x8F

struct CodecRateStruct
{
   WORD Rate;
   BYTE FSVal;
};

struct Gf1RateStruct
{
   WORD Rate;
   BYTE Voices;
};

//=============================================================================
// Reference variables in SND_DOS.C
//=============================================================================
extern short *dma_buffer;

//=============================================================================
// GUS-only variables
//=============================================================================
static BYTE HaveCodec=0;

static WORD CodecRegisterSelect;
static WORD CodecData;
static WORD CodecStatus;
static WORD Gf1TimerControl;
static WORD Gf1PageRegister;
static WORD Gf1RegisterSelect;
static WORD Gf1DataLow;
static WORD Gf1DataHigh;

static BYTE DmaChannel;

static BYTE PageRegs[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
static BYTE AddrRegs[] = { 0, 2, 4, 6, 0xc0, 0xc4, 0xc8, 0xcc };
static BYTE CountRegs[] = { 1, 3, 5, 7, 0xc2, 0xc6, 0xca, 0xce };

static WORD AddrReg;
static WORD CountReg;
static WORD ModeReg;
static WORD DisableReg;
static WORD ClearReg;

static struct CodecRateStruct CodecRates[]=
{
   { 5512,0x01},
   { 6620,0x0F},
   { 8000,0x00},
   { 9600,0x0E},
   {11025,0x03},
   {16000,0x02},
   {18900,0x05},
   {22050,0x07},
   {27420,0x04},
   {32000,0x06},
   {33075,0x0D},
   {37800,0x09},
   {44100,0x0B},
   {48000,0x0C},
   {    0,0x00} // End marker
};

static struct Gf1RateStruct Gf1Rates[]=
{
   {19293,32},
   {19916,31},
   {20580,30},
   {21289,29},
   {22050,28},
   {22866,27},
   {23746,26},
   {24696,25},
   {25725,24},
   {26843,23},
   {28063,22},
   {29400,21},
   {30870,20},
   {32494,19},
   {34300,18},
   {36317,17},
   {38587,16},
   {41160,15},
   {44100,14},
   {0,0}
};

//=============================================================================
// Basic GF1 functions
//=============================================================================
void SetGf18(BYTE reg,BYTE data)
{
   dos_outportb(Gf1RegisterSelect,reg);
   dos_outportb(Gf1DataHigh,data);
}

void SetGf116(BYTE reg,WORD data)
{
   dos_outportb(Gf1RegisterSelect,reg);
   dos_outportw(Gf1DataLow,data);
}

BYTE GetGf18(BYTE reg)
{
   dos_outportb(Gf1RegisterSelect,reg);
   return(dos_inportb(Gf1DataHigh));
}

WORD GetGf116(BYTE reg)
{
   dos_outportb(Gf1RegisterSelect,reg);
   return(dos_inportw(Gf1DataLow));
}

void Gf1Delay(void)
{
   int i;

   for (i=0;i<27;i++)
      dos_inportb(Gf1TimerControl);
}

DWORD ConvertTo16(DWORD Address)
{
   return( ((Address>>1) & 0x0001FFFF) | (Address & 0x000C0000L) );
}

void ClearGf1Ints(void)
{
   int i;

   SetGf18(DMA_CONTROL,0x00);
   SetGf18(ADLIB_CONTROL,0x00);
   SetGf18(RECORD_CONTROL,0x00);

   GetGf18(DMA_CONTROL);
   GetGf18(RECORD_CONTROL);
   for (i=0;i<32;i++);
      GetGf18(GET_IRQV);
}


//=============================================================================
// Get Interwave (UltraSound PnP) configuration if any
//=============================================================================
static qboolean GUS_GetIWData(void)
{
   char *Interwave,s[INI_STRING_SIZE];
   FILE *IwFile;
   int  CodecBase,CodecDma,i;

   Interwave=getenv("INTERWAVE");
   if (Interwave==NULL)
      return(false);

   // Open IW.INI
   IwFile=ini_fopen(Interwave,"rt");
   if (IwFile==NULL)
      return(false);

   // Read codec base and codec DMA
   ini_fgets(IwFile,"setup 0","CodecBase",s);
   sscanf(s,"%X",&CodecBase);
   ini_fgets(IwFile,"setup 0","DMA2",s);
   sscanf(s,"%i",&CodecDma);

   ini_fclose(IwFile);

   // Make sure numbers OK
   if (CodecBase==0 || CodecDma==0)
      return(false);

   CodecRegisterSelect=CodecBase;
   CodecData=CodecBase+1;
   CodecStatus=CodecBase+2;
   DmaChannel=CodecDma;

   // Make sure there is a CODEC at the CODEC base

   // Clear any pending IRQs
   dos_inportb(CodecStatus);
   dos_outportb(CodecStatus,0);

   // Wait for 'INIT' bit to clear
   for (i=0;i<0xFFFF;i++)
      if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0)
         break;
   if (i==0xFFFF)
      return(false);

   // Get chip revision - can not be zero
   dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID);
   if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID)
      return(false);
   if ((dos_inportb(CodecData) & 0x0F) == 0)
      return(false);

   HaveCodec=1;
   Con_Printf("Sound Card is UltraSound PnP\n");
   return(true);
}

//=============================================================================
// Get UltraSound MAX configuration if any
//=============================================================================
static qboolean GUS_GetMAXData(void)
{
   char *Ultrasnd,*Ultra16;
   int  i;
   int  GusBase,Dma1,Dma2,Irq1,Irq2;
   int  CodecBase,CodecDma,CodecIrq,CodecType;
   BYTE MaxVal;

   Ultrasnd=getenv("ULTRASND");
   Ultra16=getenv("ULTRA16");
   if (Ultrasnd==NULL || Ultra16==NULL)
      return(false);

   sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2);
   sscanf(Ultra16,"%x,%i,%i,%i",&CodecBase,&CodecDma,&CodecIrq,&CodecType);

   if (CodecType==0 && CodecDma!=0)
      DmaChannel=CodecDma & 0x07;
   else
      DmaChannel=Dma2 & 0x07;

   // Make sure there is a GUS at GUS base
   dos_outportb(GusBase+0x08,0x55);
   if (dos_inportb(GusBase+0x0A)!=0x55)
      return(false);
   dos_outportb(GusBase+0x08,0xAA);
   if (dos_inportb(GusBase+0x0A)!=0xAA)
      return(false);

   // Program CODEC control register
   MaxVal=((CodecBase & 0xF0)>>4) | 0x40;
   if (Dma1 > 3)
      MaxVal|=0x10;
   if (Dma2 > 3)
      MaxVal|=0x20;
   dos_outportb(GusBase+0x106,MaxVal);

   CodecRegisterSelect=CodecBase;
   CodecData=CodecBase+1;
   CodecStatus=CodecBase+2;

   // Make sure there is a CODEC at the CODEC base

   // Clear any pending IRQs
   dos_inportb(CodecStatus);
   dos_outportb(CodecStatus,0);

   // Wait for 'INIT' bit to clear
   for (i=0;i<0xFFFF;i++)
      if ((dos_inportb(CodecRegisterSelect) & 0x80) == 0)
         break;
   if (i==0xFFFF)
      return(false);

   // Get chip revision - can not be zero
   dos_outportb(CodecRegisterSelect,CODEC_MODE_AND_ID);
   if ((dos_inportb(CodecRegisterSelect) & 0x7F) != CODEC_MODE_AND_ID)
      return(false);
   if ((dos_inportb(CodecData) & 0x0F) == 0)
      return(false);

   HaveCodec=1;
   Con_Printf("Sound Card is UltraSound MAX\n");
   return(true);
}

//=============================================================================
// Get regular UltraSound configuration if any
//=============================================================================
static qboolean GUS_GetGUSData(void)
{
   char *Ultrasnd;
   int  GusBase,Dma1,Dma2,Irq1,Irq2,i;

   Ultrasnd=getenv("ULTRASND");
   if (Ultrasnd==NULL)
      return(false);

   sscanf(Ultrasnd,"%x,%i,%i,%i,%i",&GusBase,&Dma1,&Dma2,&Irq1,&Irq2);

   DmaChannel=Dma1 & 0x07;

   // Make sure there is a GUS at GUS base
   dos_outportb(GusBase+0x08,0x55);
   if (dos_inportb(GusBase+0x0A)!=0x55)
      return(false);
   dos_outportb(GusBase+0x08,0xAA);
   if (dos_inportb(GusBase+0x0A)!=0xAA)
      return(false);

   Gf1TimerControl   = GusBase+0x008;
   Gf1PageRegister   = GusBase+0x102;
   Gf1RegisterSelect = GusBase+0x103;
   Gf1DataLow        = GusBase+0x104;
   Gf1DataHigh       = GusBase+0x105;

   // Reset the GUS
   SetGf18(MASTER_RESET,0x00);
   Gf1Delay();
   Gf1Delay();
   SetGf18(MASTER_RESET,0x01);
   Gf1Delay();
   Gf1Delay();

   // Set to max (32) voices
   SetGf18(SET_VOICES,0xDF);

   // Clear any pending IRQ's
   ClearGf1Ints();

   // Set all registers to known values
   for (i=0;i<32;i++)
   {
      dos_outportb(Gf1PageRegister,i);
      SetGf18(SET_CONTROL,0x03);
      SetGf18(SET_VOLUME_CONTROL,0x03);
      Gf1Delay();
      SetGf18(SET_CONTROL,0x03);
      SetGf18(SET_VOLUME_CONTROL,0x03);
      SetGf116(SET_START_HIGH,0);
      SetGf116(SET_START_LOW,0);
      SetGf116(SET_END_HIGH,0);
      SetGf116(SET_END_LOW,0);
      SetGf116(SET_ACC_HIGH,0);
      SetGf116(SET_ACC_LOW,0);
      SetGf18(SET_VOLUME_RATE,63);
      SetGf18(SET_VOLUME_START,5);
      SetGf18(SET_VOLUME_END,251);
      SetGf116(SET_VOLUME,5<<8);
   }

   // Clear any pending IRQ's
   ClearGf1Ints();

   // Enable DAC etc.
   SetGf18(MASTER_RESET,0x07);

   // Enable line output so we can hear something
   dos_outportb(GusBase,0x08);

   HaveCodec=0;
   Con_Printf("Sound Card is UltraSound\n");
   return(true);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -