From 6027e7710fc4974d734ced4683a1f322bb377247 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Thu, 22 Feb 2007 08:39:06 +0000 Subject: [PATCH] improve mixer controls a bit. (Srecko) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2815 --- src/hardware/sblaster.cpp | 157 +++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 46 deletions(-) diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index be63f8ba..99ddbcac 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sblaster.cpp,v 1.61 2007-01-08 19:59:06 qbix79 Exp $ */ +/* $Id: sblaster.cpp,v 1.62 2007-02-22 08:39:06 qbix79 Exp $ */ #include #include @@ -949,12 +949,12 @@ static void CTMIXER_Reset(void) { CTMIXER_UpdateVolumes(); } -#define SETPROVOL(_WHICH_,_VAL_) \ - _WHICH_[0]= ((sb.type==SBT_16) ? ((_VAL_) & 0x1) :0x1) | (((_VAL_) & 0xf0) >> 3); \ - _WHICH_[1]= ((sb.type==SBT_16) ? (((_VAL_) >> 4) & 0x1) :0x1) | (((_VAL_) & 0x0f) << 1); \ +#define SETPROVOL(_WHICH_,_VAL_) \ + _WHICH_[0]= ((((_VAL_) & 0xf0) >> 3)|(sb.type==SBT_16 ? 1:3)); \ + _WHICH_[1]= ((((_VAL_) & 0x0f) << 1)|(sb.type==SBT_16 ? 1:3)); \ #define MAKEPROVOL(_WHICH_) \ - (((_WHICH_[0] & 0x1e) << 3) | ((_WHICH_[1] & 0x1e) >> 1)) + (((_WHICH_[0] & 0x1e) << 3) | ((_WHICH_[1] & 0x1e) >> 1) & (sb.type==SBT_16 ? 0xff:0xee)) static void DSP_ChangeStereo(bool stereo) { if (!sb.dma.stereo && stereo) { @@ -967,7 +967,7 @@ static void DSP_ChangeStereo(bool stereo) { sb.dma.mul/=2; sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH; sb.dma.min=(sb.dma.rate*3)/1000; - } + } sb.dma.stereo=stereo; } @@ -977,25 +977,27 @@ static void CTMIXER_Write(Bit8u val) { CTMIXER_Reset(); LOG(LOG_SB,LOG_WARN)("Mixer reset value %x",val); break; - case 0x02: /* Master Voulme (SBPRO) Obsolete? */ - case 0x22: /* Master Volume (SBPRO) */ - SETPROVOL(sb.mixer.master,val); + case 0x02: /* Master Volume (SB2 Only) */ + SETPROVOL(sb.mixer.master,(val&0xf)|(val<<4)); CTMIXER_UpdateVolumes(); break; case 0x04: /* DAC Volume (SBPRO) */ SETPROVOL(sb.mixer.dac,val); CTMIXER_UpdateVolumes(); break; - case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ - //SETPROVOL(sb.mixer.fm,val); + case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro + FM volume (SB2 Only) */ //volume controls both channels - sb.mixer.fm[0]=sb.mixer.fm[1] = 0x1| ((val&0x0f)<<1); + SETPROVOL(sb.mixer.fm,(val&0xf)|(val<<4)); CTMIXER_UpdateVolumes(); if(val&0x60) LOG(LOG_SB,LOG_WARN)("Turned FM one channel off. not implemented %X",val); //TODO Change FM Mode if only 1 fm channel is selected break; - case 0x0a: /* Mic Level */ - sb.mixer.mic=(val & 0xf) << 1; + case 0x08: /* CDA Volume (SB2 Only) */ + SETPROVOL(sb.mixer.cda,(val&0xf)|(val<<4)); + break; + case 0x0a: /* Mic Level (SBPRO) or DAC Volume (SB2): 2-bit, 3-bit on SB16 */ + if (sb.type==SBT_2) sb.mixer.dac[0]=sb.mixer.dac[1]=((val & 0x6) << 2)|3; + else sb.mixer.mic=((val & 0x7) << 2)|(sb.type==SBT_16?1:3); break; case 0x0e: /* Output/Stereo Select */ sb.mixer.stereo=(val & 0x2) > 0; @@ -1003,42 +1005,73 @@ static void CTMIXER_Write(Bit8u val) { DSP_ChangeStereo(sb.mixer.stereo); LOG(LOG_SB,LOG_WARN)("Mixer set to %s",sb.dma.stereo ? "STEREO" : "MONO"); break; + case 0x22: /* Master Volume (SBPRO) */ + SETPROVOL(sb.mixer.master,val); + CTMIXER_UpdateVolumes(); + break; case 0x26: /* FM Volume (SBPRO) */ SETPROVOL(sb.mixer.fm,val); - CTMIXER_UpdateVolumes(); + CTMIXER_UpdateVolumes(); break; case 0x28: /* CD Audio Volume (SBPRO) */ SETPROVOL(sb.mixer.cda,val); break; - case 0x2e: /* Line-IN Volume (SBPRO) */ + case 0x2e: /* Line-in Volume (SBPRO) */ SETPROVOL(sb.mixer.lin,val); break; //case 0x20: /* Master Volume Left (SBPRO) ? */ case 0x30: /* Master Volume Left (SB16) */ - if (sb.type>=SBT_PRO2) { - SETPROVOL(sb.mixer.master,(val&0xf0)|(MAKEPROVOL(sb.mixer.master)&0x0f)); + if (sb.type==SBT_16) { + sb.mixer.master[0]=val>>3; CTMIXER_UpdateVolumes(); } break; //case 0x21: /* Master Volume Right (SBPRO) ? */ - case 0x31: /* Master Volume Right (S16) */ - if (sb.type>=SBT_PRO2) { - SETPROVOL(sb.mixer.master,((val>>4)&0x0f)|(MAKEPROVOL(sb.mixer.master)&0xf0)); + case 0x31: /* Master Volume Right (SB16) */ + if (sb.type==SBT_16) { + sb.mixer.master[1]=val>>3; CTMIXER_UpdateVolumes(); } break; - case 0x32: /* DAC Volume Left (S16) */ - if (sb.type>=SBT_PRO2) { - SETPROVOL(sb.mixer.dac,(val&0xf0)|(MAKEPROVOL(sb.mixer.dac)&0x0f)); + case 0x32: /* DAC Volume Left (SB16) */ + if (sb.type==SBT_16) { + sb.mixer.dac[0]=val>>3; CTMIXER_UpdateVolumes(); } break; - case 0x33: /* DAC Volume Right (S16) */ - if (sb.type>=SBT_PRO2) { - SETPROVOL(sb.mixer.dac,((val>>4)&0x0f)|(MAKEPROVOL(sb.mixer.dac)&0xf0)); + case 0x33: /* DAC Volume Right (SB16) */ + if (sb.type==SBT_16) { + sb.mixer.dac[1]=val>>3; CTMIXER_UpdateVolumes(); } break; + case 0x34: /* FM Volume Left (SB16) */ + if (sb.type==SBT_16) { + sb.mixer.fm[0]=val>>3; + CTMIXER_UpdateVolumes(); + } + break; + case 0x35: /* FM Volume Right (SB16) */ + if (sb.type==SBT_16) { + sb.mixer.fm[1]=val>>3; + CTMIXER_UpdateVolumes(); + } + break; + case 0x36: /* CD Volume Left (SB16) */ + if (sb.type==SBT_16) sb.mixer.cda[0]=val>>3; + break; + case 0x37: /* CD Volume Right (SB16) */ + if (sb.type==SBT_16) sb.mixer.cda[1]=val>>3; + break; + case 0x38: /* Line-in Volume Left (SB16) */ + if (sb.type==SBT_16) sb.mixer.lin[0]=val>>3; + break; + case 0x39: /* Line-in Volume Right (SB16) */ + if (sb.type==SBT_16) sb.mixer.lin[1]=val>>3; + break; + case 0x3a: + if (sb.type==SBT_16) sb.mixer.mic=val>>3; + break; case 0x80: /* IRQ Select */ sb.hw.irq=0xff; if (val & 0x1) sb.hw.irq=2; @@ -1058,28 +1091,33 @@ static void CTMIXER_Write(Bit8u val) { LOG(LOG_SB,LOG_NORMAL)("Mixer select dma8:%x dma16:%x",sb.hw.dma8,sb.hw.dma16); break; default: - if ((sb.type == SBT_2 && sb.mixer.index==0x08) || /* CD volume on SB2 */ - ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ - (sb.type == SBT_16 && sb.mixer.index >= 0x30 && sb.mixer.index <= 0x47)) /* New SB16 registers */ + + if( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ + (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */ sb.mixer.unhandled[sb.mixer.index] = val; LOG(LOG_SB,LOG_WARN)("MIXER:Write %X to unhandled index %X",val,sb.mixer.index); } } - + static Bit8u CTMIXER_Read(void) { Bit8u ret; // if ( sb.mixer.index< 0x80) LOG_MSG("Read mixer %x",sb.mixer.index); switch (sb.mixer.index) { case 0x00: /* RESET */ return 0x00; - case 0x02: /* Master Voulme (SBPRO) Obsolete? */ + case 0x02: /* Master Volume (SB2 Only) */ + return ((sb.mixer.master[1]>>1) & 0xe); case 0x22: /* Master Volume (SBPRO) */ return MAKEPROVOL(sb.mixer.master); case 0x04: /* DAC Volume (SBPRO) */ return MAKEPROVOL(sb.mixer.dac); -// case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ - case 0x0a: /* Mic Level (SBPRO) */ - return (sb.mixer.mic >> 1); + case 0x06: /* FM Volume (SB2 Only) + FM output selection */ + return ((sb.mixer.fm[1]>>1) & 0xe); + case 0x08: /* CD Volume (SB2 Only) */ + return ((sb.mixer.cda[1]>>1) & 0xe); + case 0x0a: /* Mic Level (SBPRO) or Voice (SB2 Only) */ + if (sb.type==SBT_2) return (sb.mixer.dac[0]>>2); + else return ((sb.mixer.mic >> 2) & (sb.type==SBT_16 ? 7:6)); case 0x0e: /* Output/Stereo Select */ return 0x11|(sb.mixer.stereo ? 0x02 : 0x00)|(sb.mixer.filtered ? 0x20 : 0x00); case 0x26: /* FM Volume (SBPRO) */ @@ -1089,19 +1127,47 @@ static Bit8u CTMIXER_Read(void) { case 0x2e: /* Line-IN Volume (SBPRO) */ return MAKEPROVOL(sb.mixer.lin); case 0x30: /* Master Volume Left (SB16) */ - if (sb.type>=SBT_PRO2) return sb.mixer.master[0]<<3; + if (sb.type==SBT_16) return sb.mixer.master[0]<<3; ret=0xa; break; case 0x31: /* Master Volume Right (S16) */ - if (sb.type>=SBT_PRO2) return sb.mixer.master[1]<<3; + if (sb.type==SBT_16) return sb.mixer.master[1]<<3; ret=0xa; break; - case 0x32: /* DAC Volume Left (S16) */ - if (sb.type>=SBT_PRO2) return sb.mixer.dac[0]<<3; + case 0x32: /* DAC Volume Left (SB16) */ + if (sb.type==SBT_16) return sb.mixer.dac[0]<<3; ret=0xa; break; - case 0x33: /* DAC Volume Right (S16) */ - if (sb.type>=SBT_PRO2) return sb.mixer.dac[1]<<3; + case 0x33: /* DAC Volume Right (SB16) */ + if (sb.type==SBT_16) return sb.mixer.dac[1]<<3; + ret=0xa; + break; + case 0x34: /* FM Volume Left (SB16) */ + if (sb.type==SBT_16) return sb.mixer.fm[0]<<3; + ret=0xa; + break; + case 0x35: /* FM Volume Right (SB16) */ + if (sb.type==SBT_16) return sb.mixer.fm[1]<<3; + ret=0xa; + break; + case 0x36: /* CD Volume Left (SB16) */ + if (sb.type==SBT_16) return sb.mixer.cda[0]<<3; + ret=0xa; + break; + case 0x37: /* CD Volume Right (SB16) */ + if (sb.type==SBT_16) return sb.mixer.cda[1]<<3; + ret=0xa; + break; + case 0x38: /* Line-in Volume Left (SB16) */ + if (sb.type==SBT_16) return sb.mixer.lin[0]<<3; + ret=0xa; + break; + case 0x39: /* Line-in Volume Right (SB16) */ + if (sb.type==SBT_16) return sb.mixer.lin[1]<<3; + ret=0xa; + break; + case 0x3a: /* Mic Volume (SB16) */ + if (sb.type==SBT_16) return sb.mixer.mic<<3; ret=0xa; break; case 0x80: /* IRQ Select */ @@ -1124,13 +1190,12 @@ static Bit8u CTMIXER_Read(void) { case 7:ret|=0x80;break; } return ret; - case 0x82: + case 0x82: /* IRQ Status */ return (sb.irq.pending_8bit ? 0x1 : 0) | (sb.irq.pending_16bit ? 0x2 : 0); - default: /* IRQ Status */ - if ((sb.type == SBT_2 && sb.mixer.index==0x08) || /* CD volume on SB2 */ - ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ - (sb.type == SBT_16 && sb.mixer.index >= 0x30 && sb.mixer.index <= 0x47)) /* New SB16 registers */ + default: + if ( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ + (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */ ret = sb.mixer.unhandled[sb.mixer.index]; else ret=0xa;