DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/adlib.h
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #ifndef DOSBOX_ADLIB_H
00021 #define DOSBOX_ADLIB_H
00022 
00023 #include "dosbox.h"
00024 #include "mixer.h"
00025 #include "inout.h"
00026 #include "setup.h"
00027 #include "pic.h"
00028 #include "hardware.h"
00029 
00030 
00031 namespace Adlib {
00032 
00033 struct Timer {
00034         double start;
00035         double delay;
00036         bool enabled, overflow, masked;
00037         Bit8u counter;
00038         Timer() {
00039                 masked = false;
00040                 overflow = false;
00041                 enabled = false;
00042                 counter = 0;
00043                 delay = 0;
00044         }
00045         //Call update before making any further changes
00046         void Update( double time ) {
00047                 if ( !enabled || !delay ) 
00048                         return;
00049                 double deltaStart = time - start;
00050                 //Only set the overflow flag when not masked
00051                 if ( deltaStart >= 0 && !masked ) {
00052                         overflow = 1;
00053                 }
00054         }
00055         //On a reset make sure the start is in sync with the next cycle
00056         void Reset(const double& time ) {
00057                 overflow = false;
00058                 if ( !delay || !enabled )
00059                         return;
00060                 double delta = (time - start);
00061                 double rem = fmod( delta, delay );
00062                 double next = delay - rem;
00063                 start = time + next;            
00064         }
00065         void Stop( ) {
00066                 enabled = false;
00067         }
00068         void Start( const double& time, Bits scale ) {
00069                 //Don't enable again
00070                 if ( enabled ) {
00071                         return;
00072                 }
00073                 enabled = true;
00074                 delay = 0.001 * (256 - counter ) * scale;
00075                 start = time + delay;
00076         }
00077 
00078 };
00079 
00080 struct Chip {
00081         Chip() {
00082                 last_poll = 0;
00083                 poll_counter = 0;
00084         }
00085         //Last selected register
00086         Timer timer[2];
00087         //Check for it being a write to the timer
00088         bool Write( Bit32u addr, Bit8u val );
00089         //Read the current timer state, will use current double
00090         Bit8u Read( );
00091         //poll counter
00092         double last_poll;
00093         unsigned int poll_counter;
00094 };
00095 
00096 //The type of handler this is
00097 typedef enum {
00098         MODE_OPL2,
00099         MODE_DUALOPL2,
00100         MODE_OPL3
00101 } Mode;
00102 
00103 class Handler {
00104 public:
00105         //Write an address to a chip, returns the address the chip sets
00106         virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) = 0;
00107         //Write to a specific register in the chip
00108         virtual void WriteReg( Bit32u addr, Bit8u val ) = 0;
00109         //Generate a certain amount of samples
00110         virtual void Generate( MixerChannel* chan, Bitu samples ) = 0;
00111         //Initialize at a specific sample rate and mode
00112         virtual void Init( Bitu rate ) = 0;
00113 
00114         virtual ~Handler() {
00115         }
00116 };
00117 
00118 //The cache for 2 chips or an opl3
00119 typedef Bit8u RegisterCache[512];
00120 
00121 //Internal class used for dro capturing
00122 class Capture;
00123 
00124 class Module: public Module_base {
00125         IO_ReadHandleObject ReadHandler[3];
00126         IO_WriteHandleObject WriteHandler[3];
00127         MixerObject mixerObject;
00128 
00129         //Mode we're running in
00130         Mode mode;
00131         //Last selected address in the chip for the different modes
00132         union {
00133                 Bit32u normal;
00134                 Bit8u dual[2];
00135         } reg;
00136         void CacheWrite( Bit32u reg, Bit8u val );
00137         void DualWrite( Bit8u index, Bit8u reg, Bit8u val );
00138 public:
00139         static OPL_Mode oplmode;
00140         MixerChannel* mixerChan;
00141         Bit32u lastUsed;                                //Ticks when adlib was last used to turn of mixing after a few second
00142 
00143         Handler* handler;                               //Handler that will generate the sound
00144         RegisterCache cache;
00145         Capture* capture;
00146         Chip    chip[2];
00147 
00148         //Handle port writes
00149         void PortWrite( Bitu port, Bitu val, Bitu iolen );
00150         Bitu PortRead( Bitu port, Bitu iolen );
00151         void Init( Mode m );
00152 
00153         Module( Section* configuration); 
00154         ~Module();
00155 };
00156 
00157 
00158 }               //Adlib namespace
00159 
00160 #endif