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 (); }