www.pudn.com > virtual_gameboy-0.8.8.zip > IBMSB.C


/* IbmSb.c 
   This file is part of the VGB-DOS project 
   Copyright (C) Marcel de Kogel (m.dekogel@student.utwente.nl), 1996 
   You may not use this file for commercial purposes 
   Please notify me if you make any changes to this file */ 
 
/* Currently, the SB is only used for volume control */ 
 
#include "GB.h" 
#include "IbmMsDos.h" 
 
byte mastervolume=10; 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
static int got_sb=0; 
static int sb16=0; 
static unsigned sb_dsp_version; 
static word sb_port; 
static byte sb_dma_channel; 
static byte sb_irq; 
static byte sb_irq_int; 
static byte OldDacVolume[2],OldFmVolume[2],OldMasterVolume[2]; 
extern int stereomode; 
 
static int sb_read_dsp() 
{ 
 int x; 
 for (x=0; x<0xffff; x++) 
  if (inportb(0x0E + sb_port) & 0x80) 
   return inportb(0x0A+sb_port); 
 return -1;  
} 
 
static int sb_write_dsp(byte val) 
{ 
 int x; 
 for (x=0; x<0xffff; x++) 
 { 
  if (!(inportb(0x0C+sb_port) & 0x80)) 
  { 
   outportb(0x0C+sb_port, val); 
   return 1; 
  } 
 } 
 return 0; 
} 
 
static void sb_write_mixer (byte reg,byte val) 
{ 
 outportb(sb_port+4, reg); 
 outportb(sb_port+5, val); 
} 
 
static byte sb_read_mixer (byte reg) 
{ 
 outportb(sb_port+4, reg); 
 return inportb(sb_port+5); 
} 
 
static void sb_setmastervolume (void) 
{ 
 if (mastervolume>15) 
  mastervolume=15; 
 if (sb16) 
 { 
  sb_write_mixer (0x30,mastervolume<<4); 
  sb_write_mixer (0x31,mastervolume<<4); 
 } 
 else 
  sb_write_mixer (0x22,mastervolume|(mastervolume<<4)); 
} 
 
static void sb_setvolumes() 
{ 
 if (sb16) 
 { 
  OldMasterVolume[0]=sb_read_mixer (0x30); 
  OldMasterVolume[1]=sb_read_mixer (0x31); 
  OldDacVolume[0]=sb_read_mixer (0x32); 
  OldDacVolume[1]=sb_read_mixer (0x33); 
  OldFmVolume[0]=sb_read_mixer (0x34); 
  OldFmVolume[1]=sb_read_mixer (0x35); 
  sb_write_mixer (0x32,0); 
  sb_write_mixer (0x33,0); 
  sb_write_mixer (0x34,0xFF); 
  sb_write_mixer (0x35,0xFF); 
 } 
 else 
 { 
  OldMasterVolume[0]=sb_read_mixer (0x22); 
  OldDacVolume[0]=sb_read_mixer (4); 
  OldFmVolume[0]=sb_read_mixer (0x26); 
  sb_write_mixer (4,0); 
  sb_write_mixer (0x26,0xFF); 
 } 
 sb_setmastervolume (); 
} 
 
void sb_setfmvolume (int left,int right) 
{ 
 int tmp; 
 if (left>15) 
  left=15; 
 if (right>15) 
  right=15; 
 switch (stereomode) 
 { 
  case 0: 
   left=right=(left+right)/2; 
   break; 
  case 1: 
   break; 
  default: 
   tmp=left; left=right; right=tmp; 
   break; 
 } 
 if (sb16) 
 { 
  sb_write_mixer (0x34,left<<4); 
  sb_write_mixer (0x35,right<<4); 
 } 
 else 
  sb_write_mixer (0x26,(left<<4)|right); 
} 
 
static void sb_resetvolumes(void) 
{ 
 if (mastervolume>15) 
  mastervolume=15; 
 if (sb16) 
 { 
  sb_write_mixer (0x30,OldMasterVolume[0]); 
  sb_write_mixer (0x31,OldMasterVolume[1]); 
  sb_write_mixer (0x32,OldDacVolume[0]); 
  sb_write_mixer (0x33,OldDacVolume[1]); 
  sb_write_mixer (0x34,OldFmVolume[0]); 
  sb_write_mixer (0x35,OldFmVolume[1]); 
 } 
 else 
 { 
  sb_write_mixer (0x22,OldMasterVolume[0]); 
  sb_write_mixer (4,OldDacVolume[0]); 
  sb_write_mixer (0x26,OldFmVolume[0]); 
 } 
} 
 
void sb_increasemastervolume (void) 
{ 
 if (mastervolume==15) 
  return; 
 ++mastervolume; 
 sb_setmastervolume (); 
} 
 
void sb_decreasemastervolume (void) 
{ 
 if (mastervolume==0) 
  return; 
 --mastervolume; 
 sb_setmastervolume (); 
} 
 
static int sb_reset_dsp() 
{ 
 int i; 
 for (i=0;i<16;++i) 
 { 
  outportb(0x06+sb_port, 1); 
  inportb (0x06+sb_port); 
  inportb (0x06+sb_port); 
  inportb (0x06+sb_port); 
  inportb (0x06+sb_port); 
  outportb(0x06+sb_port, 0); 
  if (sb_read_dsp() == 0xAA) 
   return 1; 
 } 
 return 0; 
} 
 
static unsigned sb_read_dsp_version() 
{ 
 unsigned hi, lo; 
 sb_write_dsp(0xE1); 
 hi = sb_read_dsp(); 
 lo = sb_read_dsp(); 
 return ((hi << 8) + lo); 
} 
 
static int sb_detect() 
{ 
 sb_port=SB_Info.baseport; 
 sb_dma_channel=SB_Info.dma_low; 
 sb_irq=SB_Info.irq; 
 sb_irq_int=(sb_irq<8)? sb_irq+8 : sb_irq+0x70-8; 
 if (sb_port==0) 
  return 0; 
 if (!sb_reset_dsp()) 
  return 0; 
 sb_dsp_version=sb_read_dsp_version(); 
 if (sb_dsp_version<0x300) 
  return 0; 
 if (sb_dsp_version>=0x400) 
  sb16=1; 
 return 1; 
} 
 
int sb_init(void) 
{ 
 if (!sb_detect()) 
  return 0; 
 sb_setvolumes (); 
 got_sb=1; 
 return 1+sb16; 
} 
 
void sb_exit(void) 
{ 
 if (!got_sb) 
  return; 
 sb_resetvolumes (); 
}