1 /* 2 * Copyright (C) 2002-2015 The DOSBox Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 20 #ifndef DOSBOX_ADLIB_H 21 #define DOSBOX_ADLIB_H 22 23 #include "dosbox.h" 24 #include "mixer.h" 25 #include "inout.h" 26 #include "setup.h" 27 #include "pic.h" 28 #include "hardware.h" 29 30 31 namespace Adlib { 32 33 struct Timer { 34 double start; 35 double delay; 36 bool enabled, overflow, masked; 37 Bit8u counter; TimerTimer38 Timer() { 39 masked = false; 40 overflow = false; 41 enabled = false; 42 counter = 0; 43 delay = 0; 44 } 45 //Call update before making any further changes UpdateTimer46 void Update( double time ) { 47 if ( !enabled || !delay ) 48 return; 49 double deltaStart = time - start; 50 //Only set the overflow flag when not masked 51 if ( deltaStart >= 0 && !masked ) { 52 overflow = 1; 53 } 54 } 55 //On a reset make sure the start is in sync with the next cycle ResetTimer56 void Reset(const double& time ) { 57 overflow = false; 58 if ( !delay || !enabled ) 59 return; 60 double delta = (time - start); 61 double rem = fmod( delta, delay ); 62 double next = delay - rem; 63 start = time + next; 64 } StopTimer65 void Stop( ) { 66 enabled = false; 67 } StartTimer68 void Start( const double& time, Bits scale ) { 69 //Don't enable again 70 if ( enabled ) { 71 return; 72 } 73 enabled = true; 74 delay = 0.001 * (256 - counter ) * scale; 75 start = time + delay; 76 } 77 78 }; 79 80 struct Chip { 81 //Last selected register 82 Timer timer[2]; 83 //Check for it being a write to the timer 84 bool Write( Bit32u addr, Bit8u val ); 85 //Read the current timer state, will use current double 86 Bit8u Read( ); 87 }; 88 89 //The type of handler this is 90 typedef enum { 91 MODE_OPL2, 92 MODE_DUALOPL2, 93 MODE_OPL3, 94 MODE_OPL3GOLD 95 } Mode; 96 97 class Handler { 98 public: 99 //Write an address to a chip, returns the address the chip sets 100 virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) = 0; 101 //Write to a specific register in the chip 102 virtual void WriteReg( Bit32u addr, Bit8u val ) = 0; 103 //Generate a certain amount of samples 104 virtual void Generate( MixerChannel* chan, Bitu samples ) = 0; 105 //Initialize at a specific sample rate and mode 106 virtual void Init( Bitu rate ) = 0; ~Handler()107 virtual ~Handler() { 108 } 109 }; 110 111 //The cache for 2 chips or an opl3 112 typedef Bit8u RegisterCache[512]; 113 114 //Internal class used for dro capturing 115 class Capture; 116 117 class Module: public Module_base { 118 IO_ReadHandleObject ReadHandler[3]; 119 IO_WriteHandleObject WriteHandler[3]; 120 MixerObject mixerObject; 121 122 //Mode we're running in 123 Mode mode; 124 //Last selected address in the chip for the different modes 125 union { 126 Bit32u normal; 127 Bit8u dual[2]; 128 } reg; 129 struct { 130 bool active; 131 Bit8u index; 132 Bit8u lvol; 133 Bit8u rvol; 134 bool mixer; 135 } ctrl; 136 void CacheWrite( Bit32u reg, Bit8u val ); 137 void DualWrite( Bit8u index, Bit8u reg, Bit8u val ); 138 void CtrlWrite( Bit8u val ); 139 Bitu CtrlRead( void ); 140 public: 141 static OPL_Mode oplmode; 142 MixerChannel* mixerChan; 143 Bit32u lastUsed; //Ticks when adlib was last used to turn of mixing after a few second 144 145 Handler* handler; //Handler that will generate the sound 146 RegisterCache cache; 147 Capture* capture; 148 Chip chip[2]; 149 150 //Handle port writes 151 void PortWrite( Bitu port, Bitu val, Bitu iolen ); 152 Bitu PortRead( Bitu port, Bitu iolen ); 153 void Init( Mode m ); 154 155 Module( Section* configuration); 156 ~Module(); 157 }; 158 159 160 } //Adlib namespace 161 162 #endif 163