DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/gus.cpp
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 #include <string.h>
00021 #include <iomanip>
00022 #include <sstream>
00023 #include "dosbox.h"
00024 #include "inout.h"
00025 #include "mixer.h"
00026 #include "dma.h"
00027 #include "pic.h"
00028 #include "control.h"
00029 #include "setup.h"
00030 #include "shell.h"
00031 #include "math.h"
00032 #include "regs.h"
00033 using namespace std;
00034 
00035 #if defined(_MSC_VER)
00036 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
00037 #endif
00038 
00039 enum GUSType {
00040         GUS_CLASSIC=0,
00041         GUS_MAX,
00042         GUS_INTERWAVE
00043 };
00044 
00045 //Extra bits of precision over normal gus
00046 #define WAVE_BITS 2
00047 #define WAVE_FRACT (9+WAVE_BITS)
00048 #define WAVE_FRACT_MASK ((1 << WAVE_FRACT)-1)
00049 #define WAVE_MSWMASK ((1 << (16+WAVE_BITS))-1)
00050 #define WAVE_LSWMASK (0xffffffff ^ WAVE_MSWMASK)
00051 
00052 //Amount of precision the volume has
00053 #define RAMP_FRACT (10)
00054 #define RAMP_FRACT_MASK ((1 << RAMP_FRACT)-1)
00055 
00056 #define GUS_BASE myGUS.portbase
00057 #define GUS_RATE myGUS.rate
00058 #define LOG_GUS 0
00059 
00060 // fixed panning table (avx)
00061 static Bit16u const pantablePDF[16] = { 0, 13, 26, 41, 57, 72, 94, 116, 141, 169, 203, 244, 297, 372, 500, 4095 };
00062 static bool gus_fixed_table = false;
00063 
00064 Bit8u adlib_commandreg;
00065 static MixerChannel * gus_chan;
00066 static Bit8u const irqtable[8] = { 0/*invalid*/, 2, 5, 3, 7, 11, 12, 15 };
00067 static Bit8u const dmatable[8] = { 0/*NO DMA*/, 1, 3, 5, 6, 7, 0/*invalid*/, 0/*invalid*/ };
00068 static Bit8u GUSRam[1024*1024 + 16/*safety margin*/]; // 1024K of GUS Ram
00069 static Bit32s AutoAmp = 512;
00070 static bool enable_autoamp = false;
00071 static Bit16u vol16bit[4096];
00072 static Bit32u pantable[16];
00073 static enum GUSType gus_type = GUS_CLASSIC;
00074 static bool gus_ics_mixer = false;
00075 static bool gus_warn_irq_conflict = false;
00076 static bool gus_warn_dma_conflict = false;
00077 
00078 class GUSChannels;
00079 static void CheckVoiceIrq(void);
00080 
00081 struct GFGus {
00082         Bit8u gRegSelectData;           // what is read back from 3X3. not necessarily the index selected, but
00083                                         // apparently the last byte read OR written to ports 3X3-3X5 as seen
00084                                         // on actual GUS hardware.
00085         Bit8u gRegSelect;
00086         Bit16u gRegData;
00087         Bit32u gDramAddr;
00088         Bit16u gCurChannel;
00089 
00090         Bit8u gUltraMAXControl;
00091         Bit8u DMAControl;
00092         Bit16u dmaAddr;
00093         Bit8u dmaAddrOffset; /* bits 0-3 of the addr */
00094         Bit8u TimerControl;
00095         Bit8u SampControl;
00096         Bit8u mixControl;
00097         Bit8u ActiveChannels;
00098         Bit8u ActiveChannelsUser; /* what the guest wrote */
00099         Bit8u gRegControl;
00100         Bit32u basefreq;
00101 
00102         struct GusTimer {
00103                 float delay;
00104                 Bit8u value;
00105                 bool reached;
00106                 bool raiseirq;
00107                 bool masked;
00108                 bool running;
00109         } timers[2];
00110         Bit32u rate;
00111         Bitu portbase;
00112         Bit32u memsize;
00113         Bit8u dma1;
00114         Bit8u dma2;
00115 
00116         Bit8u irq1;             // GF1 IRQ
00117         Bit8u irq2;             // MIDI IRQ
00118 
00119         bool irqenabled;
00120         bool ChangeIRQDMA;
00121         bool initUnmaskDMA;
00122         bool force_master_irq_enable;
00123         bool fixed_sample_rate_output;
00124         bool clearTCIfPollingIRQStatus;
00125         double lastIRQStatusPollAt;
00126         int lastIRQStatusPollRapidCount;
00127         // IRQ status register values
00128         Bit8u IRQStatus;
00129         Bit32u ActiveMask;
00130         Bit8u IRQChan;
00131         Bit32u RampIRQ;
00132         Bit32u WaveIRQ;
00133 } myGUS;
00134 
00135 Bitu DEBUG_EnableDebugger(void);
00136 
00137 // Returns a single 16-bit sample from the Gravis's RAM
00138 static INLINE Bit32s GetSample(Bit32u Delta, Bit32u CurAddr, bool eightbit) {
00139         Bit32u useAddr;
00140         Bit32u holdAddr;
00141         useAddr = CurAddr >> WAVE_FRACT;
00142         if (eightbit) {
00143                 if (Delta >= (1 << WAVE_FRACT)) {
00144                         Bit32s tmpsmall = (Bit8s)GUSRam[useAddr];
00145                         return tmpsmall << 8;
00146                 } else {
00147                         // Interpolate
00148                         Bit32s w1 = ((Bit8s)GUSRam[useAddr+0]) << 8;
00149                         Bit32s w2 = ((Bit8s)GUSRam[useAddr+1]) << 8;
00150                         Bit32s diff = w2 - w1;
00151                         return (w1+((diff*(Bit32s)(CurAddr&WAVE_FRACT_MASK ))>>WAVE_FRACT));
00152                 }
00153         } else {
00154                 // Formula used to convert addresses for use with 16-bit samples
00155                 holdAddr = useAddr & 0xc0000L;
00156                 useAddr = useAddr & 0x1ffffL;
00157                 useAddr = useAddr << 1;
00158                 useAddr = (holdAddr | useAddr);
00159 
00160                 if(Delta >= (1 << WAVE_FRACT)) {
00161                         return (GUSRam[useAddr+0] | (((Bit8s)GUSRam[useAddr+1]) << 8));
00162                 } else {
00163                         // Interpolate
00164                         Bit32s w1 = (GUSRam[useAddr+0] | (((Bit8s)GUSRam[useAddr+1]) << 8));
00165                         Bit32s w2 = (GUSRam[useAddr+2] | (((Bit8s)GUSRam[useAddr+3]) << 8));
00166                         Bit32s diff = w2 - w1;
00167                         return (w1+((diff*(Bit32s)(CurAddr&WAVE_FRACT_MASK ))>>WAVE_FRACT));
00168                 }
00169         }
00170 }
00171 
00172 static uint8_t GUS_reset_reg = 0;
00173 
00174 static inline uint8_t read_GF1_mapping_control(const unsigned int ch);
00175 
00176 class GUSChannels {
00177 public:
00178         Bit32u WaveStart;
00179         Bit32u WaveEnd;
00180         Bit32u WaveAddr;
00181         Bit32u WaveAdd;
00182         Bit8u  WaveCtrl;
00183         Bit16u WaveFreq;
00184 
00185         Bit32u RampStart;
00186         Bit32u RampEnd;
00187         Bit32u RampVol;
00188         Bit32u RampAdd;
00189         Bit32u RampAddReal;
00190 
00191         Bit8u RampRate;
00192         Bit8u RampCtrl;
00193 
00194         Bit8u PanPot;
00195         Bit8u channum;
00196         Bit32u irqmask;
00197         Bit32u PanLeft;
00198         Bit32u PanRight;
00199         Bit32s VolLeft;
00200         Bit32s VolRight;
00201 
00202         GUSChannels(Bit8u num) { 
00203                 channum = num;
00204                 irqmask = 1u << num;
00205                 WaveStart = 0;
00206                 WaveEnd = 0;
00207                 WaveAddr = 0;
00208                 WaveAdd = 0;
00209                 WaveFreq = 0;
00210                 WaveCtrl = 3;
00211                 RampRate = 0;
00212                 RampStart = 0;
00213                 RampEnd = 0;
00214                 RampCtrl = 3;
00215                 RampAdd = 0;
00216                 RampAddReal = 0;
00217                 RampVol = 0;
00218                 VolLeft = 0;
00219                 VolRight = 0;
00220                 PanLeft = 0;
00221                 PanRight = 0;
00222                 PanPot = 0x7;
00223         };
00224         void WriteWaveFreq(Bit16u val) {
00225                 WaveFreq = val;
00226                 if (myGUS.fixed_sample_rate_output) {
00227                         double frameadd = double(val >> 1)/512.0;               //Samples / original gus frame
00228                         double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << WAVE_FRACT);
00229                         WaveAdd = (Bit32u)realadd;
00230                 }
00231                 else {
00232                         WaveAdd = ((Bit32u)(val >> 1)) << ((Bit32u)(WAVE_FRACT-9));
00233                 }
00234         }
00235         void WriteWaveCtrl(Bit8u val) {
00236                 Bit32u oldirq=myGUS.WaveIRQ;
00237                 WaveCtrl = val & 0x7f;
00238 
00239                 if ((val & 0xa0)==0xa0) myGUS.WaveIRQ|=irqmask;
00240                 else myGUS.WaveIRQ&=~irqmask;
00241 
00242                 if (oldirq != myGUS.WaveIRQ) 
00243                         CheckVoiceIrq();
00244         }
00245         INLINE Bit8u ReadWaveCtrl(void) {
00246                 Bit8u ret=WaveCtrl;
00247                 if (myGUS.WaveIRQ & irqmask) ret|=0x80;
00248                 return ret;
00249         }
00250         void UpdateWaveRamp(void) { 
00251                 WriteWaveFreq(WaveFreq);
00252                 WriteRampRate(RampRate);
00253         }
00254         void WritePanPot(Bit8u val) {
00255                 PanPot = val;
00256                 PanLeft = pantable[(val & 0xf)];
00257                 PanRight = pantable[0x0f-(val & 0xf)];
00258                 UpdateVolumes();
00259         }
00260         Bit8u ReadPanPot(void) {
00261                 return PanPot;
00262         }
00263         void WriteRampCtrl(Bit8u val) {
00264                 Bit32u old=myGUS.RampIRQ;
00265                 RampCtrl = val & 0x7f;
00266                 if ((val & 0xa0)==0xa0) myGUS.RampIRQ|=irqmask;
00267                 else myGUS.RampIRQ&=~irqmask;
00268                 if (old != myGUS.RampIRQ) CheckVoiceIrq();
00269         }
00270         INLINE Bit8u ReadRampCtrl(void) {
00271                 Bit8u ret=RampCtrl;
00272                 if (myGUS.RampIRQ & irqmask) ret|=0x80;
00273                 return ret;
00274         }
00275         void WriteRampRate(Bit8u val) {
00276                 RampRate = val;
00277                 if (myGUS.fixed_sample_rate_output) {
00278                         double frameadd = (double)(RampRate & 63)/(double)(1 << (3*(val >> 6)));
00279                         double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << RAMP_FRACT);
00280                         RampAdd = (Bit32u)realadd;
00281                 }
00282                 else {
00283                         /* NTS: Note RAMP_FRACT == 10, shift = 10 - (3*(val>>6)).
00284                          * From the upper two bits, the possible shift values for 0, 1, 2, 3 are: 10, 7, 4, 1 */
00285                         RampAdd = ((Bit32u)(RampRate & 63)) << ((Bit32u)(RAMP_FRACT - (3*(val >> 6))));
00286 #if 0//SET TO 1 TO CHECK YOUR MATH!
00287                         double frameadd = (double)(RampRate & 63)/(double)(1 << (3*(val >> 6)));
00288                         double realadd = frameadd * (double)(1 << RAMP_FRACT);
00289                         Bit32u checkadd = (Bit32u)realadd;
00290                         signed long error = (signed long)checkadd - (signed long)RampAdd;
00291 
00292                         if (error < -1L || error > 1L)
00293                                 LOG_MSG("RampAdd nonfixed error %ld (%lu != %lu)",error,(unsigned long)checkadd,(unsigned long)RampAdd);
00294 #endif
00295                 }
00296         }
00297         INLINE void WaveUpdate(void) {
00298                 Bit32u WaveExtra = 0;
00299                 bool endcondition;
00300 
00301                 if ((WaveCtrl & 0x3) == 0/*voice is running*/) {
00302                         /* NTS: WaveAddr and WaveAdd are unsigned.
00303                          *      If WaveAddr <= WaveAdd going backwards, WaveAddr becomes negative, which as an unsigned integer,
00304                          *      means carrying down from the highest possible value of the integer type. Which means that if the
00305                          *      start position is less than WaveAdd the WaveAddr will skip over the start pointer and continue
00306                          *      playing downward from the top of the GUS memory, without stopping/looping as expected.
00307                          *
00308                          *      This "bug" was implemented on purpose because real Gravis Ultrasound hardware acts this way. */
00309                         if (WaveCtrl & 0x40/*backwards (direction)*/) {
00310                                 /* unsigned int subtract, mask, compare. will miss start pointer if WaveStart <= WaveAdd.
00311                                  * This bug is deliberate, accurate to real GUS hardware, do not fix. */
00312                                 WaveAddr -= WaveAdd;
00313                                 WaveAddr &= ((Bitu)1 << ((Bitu)WAVE_FRACT + (Bitu)20/*1MB*/)) - 1;
00314                                 endcondition = (WaveAddr < WaveStart)?true:false;
00315                                 if (endcondition) WaveExtra = WaveStart - WaveAddr;
00316                         }
00317                         else {
00318                                 WaveAddr += WaveAdd;
00319                                 endcondition = (WaveAddr > WaveEnd)?true:false;
00320                                 WaveAddr &= ((Bitu)1 << ((Bitu)WAVE_FRACT + (Bitu)20/*1MB*/)) - 1;
00321                                 if (endcondition) WaveExtra = WaveAddr - WaveEnd;
00322                         }
00323 
00324                         if (endcondition) {
00325                                 if (WaveCtrl & 0x20) /* generate an IRQ if requested */
00326                                         myGUS.WaveIRQ |= irqmask;
00327 
00328                                 if ((RampCtrl & 0x04/*roll over*/) && !(WaveCtrl & 0x08/*looping*/)) {
00329                                         /* "3.11. Rollover feature
00330                                          * 
00331                                          * Each voice has a 'rollover' feature that allows an application to be notified when a voice's playback position passes
00332                                          * over a particular place in DRAM.  This is very useful for getting seamless digital audio playback.  Basically, the GF1
00333                                          * will generate an IRQ when a voice's current position is  equal to the end position.  However, instead of stopping or
00334                                          * looping back to the start position, the voice will continue playing in the same direction.  This means that there will be
00335                                          * no pause (or gap) in the playback.  Note that this feature is enabled/disabled through the voice's VOLUME control
00336                                          * register (since there are no more bits available in the voice control registers).   A voice's loop enable bit takes
00337                                          * precedence over the rollover.  This means that if a voice's loop enable is on, it will loop when it hits the end position,
00338                                          * regardless of the state of the rollover enable."
00339                                          *
00340                                          * Despite the confusing description above, that means that looping takes precedence over rollover. If not looping, then
00341                                          * rollover means to fire the IRQ but keep moving. If looping, then fire IRQ and carry out loop behavior. Gravis Ultrasound
00342                                          * Windows 3.1 drivers expect this behavior, else Windows WAVE output will not work correctly. */
00343                                 }
00344                                 else {
00345                                         if (WaveCtrl & 0x08/*loop*/) {
00346                                                 if (WaveCtrl & 0x10/*bi-directional*/) WaveCtrl ^= 0x40/*change direction*/;
00347                                                 WaveAddr = (WaveCtrl & 0x40) ? (WaveEnd - WaveExtra) : (WaveStart + WaveExtra);
00348                                         } else {
00349                                                 WaveCtrl |= 1; /* stop the channel */
00350                                                 WaveAddr = (WaveCtrl & 0x40) ? WaveStart : WaveEnd;
00351                                         }
00352                                 }
00353                         }
00354                 }
00355                 else if ((WaveCtrl & 0x20)/*IRQ enabled*/) {
00356                         /* Undocumented behavior observed on real GUS hardware: A stopped voice will still rapid-fire IRQs
00357                          * if IRQ enabled and current position <= start position OR current position >= end position */
00358                         if (WaveCtrl & 0x40/*backwards (direction)*/)
00359                                 endcondition = (WaveAddr <= WaveStart)?true:false;
00360                         else
00361                                 endcondition = (WaveAddr >= WaveEnd)?true:false;
00362 
00363                         if (endcondition)
00364                                 myGUS.WaveIRQ |= irqmask;
00365                 }
00366         }
00367         INLINE void UpdateVolumes(void) {
00368                 Bit32s templeft=(Bit32s)RampVol - (Bit32s)PanLeft;
00369                 templeft&=~(templeft >> 31); /* <- NTS: This is a rather elaborate way to clamp negative values to zero using negate and sign extend */
00370                 Bit32s tempright=(Bit32s)RampVol - (Bit32s)PanRight;
00371                 tempright&=~(tempright >> 31); /* <- NTS: This is a rather elaborate way to clamp negative values to zero using negate and sign extend */
00372                 VolLeft=vol16bit[templeft >> RAMP_FRACT];
00373                 VolRight=vol16bit[tempright >> RAMP_FRACT];
00374         }
00375         INLINE void RampUpdate(void) {
00376                 if (RampCtrl & 0x3) return; /* if the ramping is turned off, then don't change the ramp */
00377 
00378                 Bit32s RampLeft;
00379                 if (RampCtrl & 0x40) {
00380                         RampVol-=RampAdd;
00381                         if ((Bit32s)RampVol < (Bit32s)0) RampVol=0;
00382                         RampLeft=(Bit32s)RampStart-(Bit32s)RampVol;
00383                 } else {
00384                         RampVol+=RampAdd;
00385                         if (RampVol > ((4096 << RAMP_FRACT)-1)) RampVol=((4096 << RAMP_FRACT)-1);
00386                         RampLeft=(Bit32s)RampVol-(Bit32s)RampEnd;
00387                 }
00388                 if (RampLeft<0) {
00389                         UpdateVolumes();
00390                         return;
00391                 }
00392                 /* Generate an IRQ if needed */
00393                 if (RampCtrl & 0x20) {
00394                         myGUS.RampIRQ|=irqmask;
00395                 }
00396                 /* Check for looping */
00397                 if (RampCtrl & 0x08) {
00398                         /* Bi-directional looping */
00399                         if (RampCtrl & 0x10) RampCtrl^=0x40;
00400                         RampVol = (RampCtrl & 0x40) ? (Bit32u)((Bit32s)RampEnd-(Bit32s)RampLeft) : (Bit32u)((Bit32s)RampStart+(Bit32s)RampLeft);
00401                 } else {
00402                         RampCtrl|=1;    //Stop the channel
00403                         RampVol = (RampCtrl & 0x40) ? RampStart : RampEnd;
00404                 }
00405                 if ((Bit32s)RampVol < (Bit32s)0) RampVol=0;
00406                 if (RampVol > ((4096 << RAMP_FRACT)-1)) RampVol=((4096 << RAMP_FRACT)-1);
00407                 UpdateVolumes();
00408         }
00409         void generateSamples(Bit32s * stream,Bit32u len) {
00410                 bool eightbit = ((WaveCtrl & 0x4) == 0);
00411                 Bit32s tmpsamp;
00412                 int i;
00413 
00414                 /* NTS: The GUS is *always* rendering the audio sample at the current position,
00415                  *      even if the voice is stopped. This can be confirmed using DOSLIB, loading
00416                  *      the Ultrasound test program, loading a WAV file into memory, then using
00417                  *      the Ultrasound test program's voice control dialog to single-step the
00418                  *      voice through RAM (abruptly change the current position) while the voice
00419                  *      is stopped. You will hear "popping" noises come out the GUS audio output
00420                  *      as the current position changes and the piece of the sample rendered
00421                  *      abruptly changes as well. */
00422                 if (gus_ics_mixer) {
00423                         const unsigned char Lc = read_GF1_mapping_control(0);
00424                         const unsigned char Rc = read_GF1_mapping_control(1);
00425 
00426                         // output mapped through ICS mixer including channel remapping
00427                         for(i=0;i<(int)len;i++) {
00428                                 // Get sample
00429                                 tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit);
00430 
00431                                 // Output stereo sample if DAC enable on
00432                                 if ((GUS_reset_reg & 0x02/*DAC enable*/) == 0x02) {
00433                                         Bit32s * const sp = stream + (i << 1);
00434                                         const Bit32s L = tmpsamp * VolLeft;
00435                                         const Bit32s R = tmpsamp * VolRight;
00436 
00437                                         if (Lc&1) sp[0] += L;
00438                                         if (Lc&2) sp[1] += L;
00439                                         if (Rc&1) sp[0] += R;
00440                                         if (Rc&2) sp[1] += R;
00441                                 }
00442 
00443                                 WaveUpdate();
00444                                 RampUpdate();
00445                         }
00446                 }
00447                 else {
00448                         // normal output
00449                         for(i=0;i<(int)len;i++) {
00450                                 // Get sample
00451                                 tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit);
00452 
00453                                 // Output stereo sample if DAC enable on
00454                                 if ((GUS_reset_reg & 0x02/*DAC enable*/) == 0x02) {
00455                                         stream[i<<1]+= tmpsamp * VolLeft;
00456                                         stream[(i<<1)+1]+= tmpsamp * VolRight;
00457                                 }
00458 
00459                                 WaveUpdate();
00460                                 RampUpdate();
00461                         }
00462                 }
00463         }
00464 };
00465 
00466 static GUSChannels *guschan[32] = {NULL};
00467 static GUSChannels *curchan = NULL;
00468 
00469 static INLINE void GUS_CheckIRQ(void);
00470 
00471 static void GUS_TimerEvent(Bitu val);
00472 
00473 static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event);
00474 
00475 void GUS_StopDMA();
00476 void GUS_StartDMA();
00477 void GUS_Update_DMA_Event_transfer();
00478 
00479 static void GUSReset(void) {
00480         unsigned char p_GUS_reset_reg = GUS_reset_reg;
00481 
00482         /* NTS: From the Ultrasound SDK:
00483          *
00484          *      Global Data Low (3X4) is either a 16-bit transfer, or the low half of a 16-bit transfer with 8-bit I/O.
00485          *
00486          *      Global Data High (3X5) is either an 8-bit transfer for one of the GF registers or the high part of a 16-bit wide register with 8-bit I/O.
00487          *
00488          *      Prior to 2015/12/29 DOSBox and DOSBox-X contained a programming error here where reset and master IRQ enable were handled from the
00489          *      LOWER 8 bits, when the code should have been checking the UPPER 8 bits. Programming error #2 was the mis-interpetation of bit 0 (bit 8 of
00490          *      the gRegData). According to the SDK, clearing bit 0 triggers RESET, setting bit 0 starts the card running again. The original code had
00491          *      it backwards. */
00492         GUS_reset_reg = (myGUS.gRegData >> 8) & 7;
00493 
00494         if ((myGUS.gRegData & 0x400) != 0x000 || myGUS.force_master_irq_enable)
00495                 myGUS.irqenabled = true;
00496         else
00497                 myGUS.irqenabled = false;
00498 
00499         LOG(LOG_MISC,LOG_DEBUG)("GUS reset with 0x%04X",myGUS.gRegData);
00500         if ((myGUS.gRegData & 0x100) == 0x000) {
00501                 // Stop all channels
00502                 int i;
00503                 for(i=0;i<32;i++) {
00504                         guschan[i]->RampVol=0;
00505                         guschan[i]->WriteWaveCtrl(0x1);
00506                         guschan[i]->WriteRampCtrl(0x1);
00507                         guschan[i]->WritePanPot(0x7);
00508                 }
00509 
00510                 // Stop DMA
00511                 GUS_StopDMA();
00512 
00513                 // Reset
00514                 adlib_commandreg = 85;
00515                 myGUS.IRQStatus = 0;
00516                 myGUS.RampIRQ = 0;
00517                 myGUS.WaveIRQ = 0;
00518                 myGUS.IRQChan = 0;
00519 
00520                 myGUS.timers[0].delay = 0.080f;
00521                 myGUS.timers[1].delay = 0.320f;
00522                 myGUS.timers[0].value = 0xff;
00523                 myGUS.timers[1].value = 0xff;
00524                 myGUS.timers[0].masked = false;
00525                 myGUS.timers[1].masked = false;
00526                 myGUS.timers[0].raiseirq = false;
00527                 myGUS.timers[1].raiseirq = false;
00528                 myGUS.timers[0].reached = true;
00529                 myGUS.timers[1].reached = true;
00530                 myGUS.timers[0].running = false;
00531                 myGUS.timers[1].running = false;
00532 
00533                 PIC_RemoveEvents(GUS_TimerEvent);
00534 
00535                 myGUS.ChangeIRQDMA = false;
00536                 myGUS.DMAControl = 0x00;
00537                 myGUS.mixControl = 0x0b;        // latches enabled by default LINEs disabled
00538                 myGUS.TimerControl = 0x00;
00539                 myGUS.SampControl = 0x00;
00540                 myGUS.ActiveChannels = 14;
00541                 myGUS.ActiveChannelsUser = 14;
00542                 myGUS.ActiveMask=0xffffffffU >> (32-myGUS.ActiveChannels);
00543                 myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)(myGUS.ActiveChannels)));
00544 
00545                 gus_chan->FillUp();
00546                 if (!myGUS.fixed_sample_rate_output)    gus_chan->SetFreq(myGUS.basefreq);
00547                 else                                    gus_chan->SetFreq(GUS_RATE);
00548 
00549                 myGUS.gCurChannel = 0;
00550                 curchan = guschan[myGUS.gCurChannel];
00551 
00552                 myGUS.dmaAddr = 0;
00553                 myGUS.irqenabled = 0;
00554                 myGUS.gRegControl = 0;
00555                 myGUS.dmaAddrOffset = 0;
00556                 myGUS.gDramAddr = 0;
00557                 myGUS.gRegData = 0;
00558 
00559                 GUS_Update_DMA_Event_transfer();
00560         }
00561 
00562         /* if the card was just put into reset, or the card WAS in reset, bits 1-2 are cleared */
00563         if ((GUS_reset_reg & 1) == 0 || (p_GUS_reset_reg & 1) == 0) {
00564                 /* GUS classic observed behavior: resetting the card, or even coming out of reset, clears bits 1-2.
00565                  * That means, if you write any value to GUS RESET with bit 0 == 0, bits 1-2 become zero as well.
00566                  * And if you take the card out of reset, bits 1-2 are zeroed.
00567                  *
00568                  * test 1:
00569                  * outb(0x3X3,0x4C); outb(0x3X5,0x00);
00570                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x00 as expected
00571                  * outb(0x3X3,0x4C); outb(0x3X5,0x07);
00572                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x01, not 0x07
00573                  *
00574                  * test 2:
00575                  * outb(0x3X3,0x4C); outb(0x3X5,0x00);
00576                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x00 as expected
00577                  * outb(0x3X3,0x4C); outb(0x3X5,0x01);
00578                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x01 as expected, card taken out of reset
00579                  * outb(0x3X3,0x4C); outb(0x3X5,0x07);
00580                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x07 as expected
00581                  * outb(0x3X3,0x4C); outb(0x3X5,0x06);    <- bit 0 == 0, we're trying to set bits 1-2
00582                  * outb(0x3X3,0x4C); c = inb(0x3X5);      <- you'll get 0x00, not 0x06, card is in reset state */
00583                 myGUS.irqenabled = myGUS.force_master_irq_enable; // IRQ enable resets, unless user specified we force it on
00584                 GUS_reset_reg &= 1;
00585         }
00586 
00587         GUS_CheckIRQ();
00588 }
00589 
00590 static uint8_t GUS_EffectiveIRQStatus(void) {
00591         uint8_t ret = 0;
00592 
00593         /* Behavior observed on real GUS hardware: Master IRQ enable bit 2 of the reset register affects only voice/wave
00594          * IRQ signals from the GF1. It does not affect the DMA terminal count interrupt nor does it affect the Adlib timers.
00595          * This is how "Juice" by Psychic Link is able to play music by GUS timer even though the demo never enables the
00596          * Master IRQ Enable bit. */
00597 
00598         /* DMA */
00599         if (myGUS.DMAControl & 0x20/*DMA IRQ Enable*/)
00600                 ret |= (myGUS.IRQStatus & 0x80/*DMA TC IRQ*/);
00601 
00602         /* Timer 1 & 2 */
00603         ret |= (myGUS.IRQStatus/*Timer 1&2 IRQ*/ & myGUS.TimerControl/*Timer 1&2 IRQ Enable*/ & 0x0C);
00604 
00605         /* Voice IRQ */
00606         if (myGUS.irqenabled)
00607                 ret |= (myGUS.IRQStatus & 0x60/*Wave/Ramp IRQ*/);
00608 
00609         /* TODO: MIDI IRQ? */
00610 
00611         return ret;
00612 }
00613 
00614 static uint8_t gus_prev_effective_irqstat = 0;
00615 
00616 static INLINE void GUS_CheckIRQ(void) {
00617         if (myGUS.mixControl & 0x08/*Enable latches*/) {
00618                 uint8_t irqstat = GUS_EffectiveIRQStatus();
00619 
00620                 if (irqstat != 0) {
00621                         /* The GUS fires an IRQ, then waits for the interrupt service routine to
00622                          * clear all pending interrupt events before firing another one. if you
00623                          * don't service all events, then you don't get another interrupt. */
00624                         if (gus_prev_effective_irqstat == 0) {
00625                                 PIC_ActivateIRQ(myGUS.irq1);
00626 
00627                 if (gus_warn_irq_conflict)
00628                                         LOG(LOG_MISC,LOG_WARN)(
00629                         "GUS warning: Both IRQs set to the same signal line WITHOUT combining! "
00630                         "This is documented to cause bus conflicts on real hardware");
00631             }
00632                 }
00633 
00634                 gus_prev_effective_irqstat = irqstat;
00635         }
00636 }
00637 
00638 static void CheckVoiceIrq(void) {
00639         Bitu totalmask=(myGUS.RampIRQ|myGUS.WaveIRQ) & myGUS.ActiveMask;
00640         if (!totalmask) {
00641                 GUS_CheckIRQ();
00642                 return;
00643         }
00644 
00645         if (myGUS.RampIRQ) myGUS.IRQStatus|=0x40;
00646         if (myGUS.WaveIRQ) myGUS.IRQStatus|=0x20;
00647         GUS_CheckIRQ();
00648         for (;;) {
00649                 Bit32u check=(1u << myGUS.IRQChan);
00650                 if (totalmask & check) return;
00651                 myGUS.IRQChan++;
00652                 if (myGUS.IRQChan>=myGUS.ActiveChannels) myGUS.IRQChan=0;
00653         }
00654 }
00655 
00656 static Bit16u ExecuteReadRegister(void) {
00657         Bit8u tmpreg;
00658 //      LOG_MSG("Read global reg %x",myGUS.gRegSelect);
00659         switch (myGUS.gRegSelect) {
00660         case 0x8E:  // read active channel register
00661                 // NTS: The GUS SDK documents the active channel count as bits 5-0, which is wrong. it's bits 4-0. bits 7-5 are always 1 on real hardware.
00662                 return ((Bit16u)(0xE0 | (myGUS.ActiveChannelsUser - 1))) << 8;
00663         case 0x41: // Dma control register - read acknowledges DMA IRQ
00664                 tmpreg = myGUS.DMAControl & 0xbf;
00665                 tmpreg |= (myGUS.IRQStatus & 0x80) >> 1;
00666                 myGUS.IRQStatus&=0x7f;
00667                 GUS_CheckIRQ();
00668                 return (Bit16u)(tmpreg << 8);
00669         case 0x42:  // Dma address register
00670                 return myGUS.dmaAddr;
00671         case 0x45:  // Timer control register.  Identical in operation to Adlib's timer
00672                 return (Bit16u)(myGUS.TimerControl << 8);
00673                 break;
00674         case 0x49:  // Dma sample register
00675                 tmpreg = myGUS.DMAControl & 0xbf;
00676                 tmpreg |= (myGUS.IRQStatus & 0x80) >> 1;
00677                 return (Bit16u)(tmpreg << 8);
00678         case 0x4c:  // GUS reset register
00679                 tmpreg = (GUS_reset_reg & ~0x4) | (myGUS.irqenabled ? 0x4 : 0x0);
00680                 /* GUS Classic observed behavior: You can read Register 4Ch from both 3X4 and 3X5 and get the same 8-bit contents */
00681                 return ((Bit16u)(tmpreg << 8) | (Bit16u)tmpreg);
00682         case 0x80: // Channel voice control read register
00683                 if (curchan) return curchan->ReadWaveCtrl() << 8;
00684                 else return 0x0300;
00685         case 0x81:  // Channel frequency control register
00686                 if(curchan) return (Bit16u)(curchan->WaveFreq);
00687                 else return 0x0000;;
00688         case 0x82: // Channel MSB start address register
00689                 if (curchan) return (Bit16u)(curchan->WaveStart >> (WAVE_BITS+16));
00690                 else return 0x0000;
00691         case 0x83: // Channel LSW start address register
00692                 if (curchan) return (Bit16u)(curchan->WaveStart >> WAVE_BITS);
00693                 else return 0x0000;
00694         case 0x84: // Channel MSB end address register
00695                 if (curchan) return (Bit16u)(curchan->WaveEnd >> (WAVE_BITS+16));
00696                 else return 0x0000;
00697         case 0x85: // Channel LSW end address register
00698                 if (curchan) return (Bit16u)(curchan->WaveEnd >> WAVE_BITS);
00699                 else return 0x0000;
00700 
00701         case 0x89: // Channel volume register
00702                 if (curchan) return (Bit16u)((curchan->RampVol >> RAMP_FRACT) << 4);
00703                 else return 0x0000;
00704         case 0x8a: // Channel MSB current address register
00705                 if (curchan) return (Bit16u)(curchan->WaveAddr >> (WAVE_BITS+16));
00706                 else return 0x0000;
00707         case 0x8b: // Channel LSW current address register
00708                 if (curchan) return (Bit16u)(curchan->WaveAddr >> WAVE_BITS);
00709                 else return 0x0000;
00710 
00711         case 0x8d: // Channel volume control register
00712                 if (curchan) return curchan->ReadRampCtrl() << 8;
00713                 else return 0x0300;
00714         case 0x8f: // General channel IRQ status register
00715                 tmpreg=myGUS.IRQChan|0x20;
00716                 Bit32u mask;
00717                 mask=1u << myGUS.IRQChan;
00718                 if (!(myGUS.RampIRQ & mask)) tmpreg|=0x40;
00719                 if (!(myGUS.WaveIRQ & mask)) tmpreg|=0x80;
00720                 myGUS.RampIRQ&=~mask;
00721                 myGUS.WaveIRQ&=~mask;
00722                 myGUS.IRQStatus&=0x9f;
00723                 CheckVoiceIrq();
00724                 return (Bit16u)(tmpreg << 8);
00725         default:
00726 #if LOG_GUS
00727                 LOG_MSG("Read Register num 0x%x", myGUS.gRegSelect);
00728 #endif
00729                 return myGUS.gRegData;
00730         }
00731 }
00732 
00733 static void GUS_TimerEvent(Bitu val) {
00734         if (!myGUS.timers[val].masked) myGUS.timers[val].reached=true;
00735         if (myGUS.timers[val].raiseirq) {
00736                 myGUS.IRQStatus|=0x4 << val;
00737                 GUS_CheckIRQ();
00738         }
00739         if (myGUS.timers[val].running) 
00740                 PIC_AddEvent(GUS_TimerEvent,myGUS.timers[val].delay,val);
00741 }
00742 
00743  
00744 static void ExecuteGlobRegister(void) {
00745         int i;
00746 //      if (myGUS.gRegSelect|1!=0x44) LOG_MSG("write global register %x with %x", myGUS.gRegSelect, myGUS.gRegData);
00747         switch(myGUS.gRegSelect) {
00748         case 0x0:  // Channel voice control register
00749                 gus_chan->FillUp();
00750                 if(curchan) curchan->WriteWaveCtrl((Bit16u)myGUS.gRegData>>8);
00751                 break;
00752         case 0x1:  // Channel frequency control register
00753                 gus_chan->FillUp();
00754                 if(curchan) curchan->WriteWaveFreq(myGUS.gRegData);
00755                 break;
00756         case 0x2:  // Channel MSW start address register
00757                 if (curchan) {
00758                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); /* upper 13 bits of integer portion */
00759                         curchan->WaveStart = (curchan->WaveStart & WAVE_MSWMASK) | tmpaddr;
00760                 }
00761                 break;
00762         case 0x3:  // Channel LSW start address register
00763                 if(curchan != NULL) {
00764                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0xffe0) << WAVE_BITS; /* lower 7 bits of integer portion, and all 4 bits of fractional portion. bits 4-0 of the incoming 16-bit WORD are not used */
00765                         curchan->WaveStart = (curchan->WaveStart & WAVE_LSWMASK) | tmpaddr;
00766                 }
00767                 break;
00768         case 0x4:  // Channel MSW end address register
00769                 if(curchan != NULL) {
00770                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); /* upper 13 bits of integer portion */
00771                         curchan->WaveEnd = (curchan->WaveEnd & WAVE_MSWMASK) | tmpaddr;
00772                 }
00773                 break;
00774         case 0x5:  // Channel MSW end address register
00775                 if(curchan != NULL) {
00776                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0xffe0) << WAVE_BITS; /* lower 7 bits of integer portion, and all 4 bits of fractional portion. bits 4-0 of the incoming 16-bit WORD are not used */
00777                         curchan->WaveEnd = (curchan->WaveEnd & WAVE_LSWMASK) | tmpaddr;
00778                 }
00779                 break;
00780         case 0x6:  // Channel volume ramp rate register
00781                 gus_chan->FillUp();
00782                 if(curchan != NULL) {
00783                         Bit8u tmpdata = (Bit16u)myGUS.gRegData>>8;
00784                         curchan->WriteRampRate(tmpdata);
00785                 }
00786                 break;
00787         case 0x7:  // Channel volume ramp start register  EEEEMMMM
00788                 if(curchan != NULL) {
00789                         Bit8u tmpdata = (Bit16u)myGUS.gRegData >> 8;
00790                         curchan->RampStart = (Bit32u)(tmpdata << (4+RAMP_FRACT));
00791                 }
00792                 break;
00793         case 0x8:  // Channel volume ramp end register  EEEEMMMM
00794                 if(curchan != NULL) {
00795                         Bit8u tmpdata = (Bit16u)myGUS.gRegData >> 8;
00796                         curchan->RampEnd = (Bit32u)(tmpdata << (4+RAMP_FRACT));
00797                 }
00798                 break;
00799         case 0x9:  // Channel current volume register
00800                 gus_chan->FillUp();
00801                 if(curchan != NULL) {
00802                         Bit16u tmpdata = (Bit16u)myGUS.gRegData >> 4;
00803                         curchan->RampVol = (Bit32u)(tmpdata << RAMP_FRACT);
00804                         curchan->UpdateVolumes();
00805                 }
00806                 break;
00807         case 0xA:  // Channel MSW current address register
00808                 gus_chan->FillUp();
00809                 if(curchan != NULL) {
00810                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); /* upper 13 bits of integer portion */
00811                         curchan->WaveAddr = (curchan->WaveAddr & WAVE_MSWMASK) | tmpaddr;
00812                 }
00813                 break;
00814         case 0xB:  // Channel LSW current address register
00815                 gus_chan->FillUp();
00816                 if(curchan != NULL) {
00817                         Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0xffff) << (WAVE_BITS); /* lower 7 bits of integer portion, and all 9 bits of fractional portion */
00818                         curchan->WaveAddr = (curchan->WaveAddr & WAVE_LSWMASK) | tmpaddr;
00819                 }
00820                 break;
00821         case 0xC:  // Channel pan pot register
00822                 gus_chan->FillUp();
00823                 if(curchan) curchan->WritePanPot((Bit16u)myGUS.gRegData>>8);
00824                 break;
00825         case 0xD:  // Channel volume control register
00826                 gus_chan->FillUp();
00827                 if(curchan) curchan->WriteRampCtrl((Bit16u)myGUS.gRegData>>8);
00828                 break;
00829         case 0xE:  // Set active channel register
00830                 gus_chan->FillUp();
00831                 myGUS.gRegSelect = myGUS.gRegData>>8;           //JAZZ Jackrabbit seems to assume this?
00832                 myGUS.ActiveChannelsUser = 1+((myGUS.gRegData>>8) & 31); // NTS: The GUS SDK documents this field as bits 5-0, which is wrong, it's bits 4-0. 5-0 would imply 64 channels.
00833 
00834                 /* The GUS SDK claims that if a channel count less than 14 is written, then it caps to 14.
00835                  * That's not true. Perhaps what the SDK is doing, but the actual hardware acts differently.
00836                  * This implementation is based on what the Gravis Ultrasound MAX actually does with this
00837                  * register. You can apparently achieve higher than 44.1KHz sample rates by programming less
00838                  * than 14 channels, and the sample rate scale ramps up appropriately, except that values
00839                  * 0 and 1 have the same effect as writing 2 and 3. Very useful undocumented behavior!
00840                  * If Gravis were smart, they would have been able to claim 48KHz sample rates by allowing
00841                  * less than 14 channels in their SDK! Not sure why they would cap it like that, unless
00842                  * there are undocumented chipset instabilities with running at higher rates.
00843                  *
00844                  * So far only verified on a Gravis Ultrasound MAX.
00845                  *
00846                  * Does anyone out there have a Gravis Ultrasound Classic (original 1992 version) they can
00847                  * test for this behavior?
00848                  *
00849                  * NOTED: Gravis Ultrasound Plug & Play (interwave) cards *do* enforce the 14-channel minimum.
00850                  *        You can write less than 14 channels to this register, but unlike the Classic and Max
00851                  *        cards they will not run faster than 44.1KHz. */
00852                 myGUS.ActiveChannels = myGUS.ActiveChannelsUser;
00853 
00854                 if (gus_type < GUS_INTERWAVE) {
00855                         // GUS MAX behavior seen on real hardware
00856                         if(myGUS.ActiveChannels < 3) myGUS.ActiveChannels += 2;
00857                         if(myGUS.ActiveChannels > 32) myGUS.ActiveChannels = 32;
00858                 }
00859                 else {
00860                         // Interwave PnP behavior seen on real hardware
00861                         if(myGUS.ActiveChannels < 14) myGUS.ActiveChannels = 14;
00862                         if(myGUS.ActiveChannels > 32) myGUS.ActiveChannels = 32;
00863                 }
00864 
00865                 myGUS.ActiveMask=0xffffffffU >> (32-myGUS.ActiveChannels);
00866                 myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)(myGUS.ActiveChannels)));
00867 
00868                 if (!myGUS.fixed_sample_rate_output)    gus_chan->SetFreq(myGUS.basefreq);
00869                 else                                    gus_chan->SetFreq(GUS_RATE);
00870 
00871 #if LOG_GUS
00872                 LOG_MSG("GUS set to %d channels fixed=%u freq=%luHz", myGUS.ActiveChannels,myGUS.fixed_sample_rate_output,(unsigned long)myGUS.basefreq);
00873 #endif
00874                 for (i=0;i<myGUS.ActiveChannels;i++) guschan[i]->UpdateWaveRamp();
00875                 break;
00876         case 0x10:  // Undocumented register used in Fast Tracker 2
00877                 break;
00878         case 0x41:  // Dma control register
00879                 myGUS.DMAControl = (Bit8u)(myGUS.gRegData>>8);
00880                 GUS_Update_DMA_Event_transfer();
00881                 if (myGUS.DMAControl & 1) GUS_StartDMA();
00882                 else GUS_StopDMA();
00883                 break;
00884         case 0x42:  // Gravis DRAM DMA address register
00885                 myGUS.dmaAddr = myGUS.gRegData;
00886                 myGUS.dmaAddrOffset = 0;
00887                 break;
00888         case 0x43:  // LSB Peek/poke DRAM position
00889                 myGUS.gDramAddr = (0xff0000 & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData);
00890                 break;
00891         case 0x44:  // MSW Peek/poke DRAM position
00892                 myGUS.gDramAddr = (0xffff & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData>>8) << 16;
00893                 break;
00894         case 0x45:  // Timer control register.  Identical in operation to Adlib's timer
00895                 myGUS.TimerControl = (Bit8u)(myGUS.gRegData>>8);
00896                 myGUS.timers[0].raiseirq=(myGUS.TimerControl & 0x04)>0;
00897                 if (!myGUS.timers[0].raiseirq) myGUS.IRQStatus&=~0x04;
00898                 myGUS.timers[1].raiseirq=(myGUS.TimerControl & 0x08)>0;
00899                 if (!myGUS.timers[1].raiseirq) myGUS.IRQStatus&=~0x08;
00900                 GUS_CheckIRQ();
00901                 break;
00902         case 0x46:  // Timer 1 control
00903                 myGUS.timers[0].value = (Bit8u)(myGUS.gRegData>>8);
00904                 myGUS.timers[0].delay = (0x100 - myGUS.timers[0].value) * 0.080f;
00905                 break;
00906         case 0x47:  // Timer 2 control
00907                 myGUS.timers[1].value = (Bit8u)(myGUS.gRegData>>8);
00908                 myGUS.timers[1].delay = (0x100 - myGUS.timers[1].value) * 0.320f;
00909                 break;
00910         case 0x49:  // DMA sampling control register
00911                 myGUS.SampControl = (Bit8u)(myGUS.gRegData>>8);
00912                 if (myGUS.DMAControl & 1) GUS_StartDMA();
00913                 else GUS_StopDMA();
00914                 break;
00915         case 0x4c:  // GUS reset register
00916                 GUSReset();
00917                 break;
00918         default:
00919 #if LOG_GUS
00920                 LOG_MSG("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData);
00921 #endif
00922                 break;
00923         }
00924         return;
00925 }
00926 
00927 /* Gravis Ultrasound ICS-2101 Digitally Controlled Audio Mixer emulation */
00928 /* NTS: This was written and tested only through Ultrasound software and emulation.
00929  *      I do not have a Gravis Ultrasound card with this type of mixer to test against. --J.C. */
00930 struct gus_ICS2101 {
00931 public:
00932         // ICS2101 and how Gravis wired up the input pairs when using it, according to some BSD and Linux kernel sources
00933         //
00934         // From the header file:
00935         //
00936         //   Register defs for Integrated Circuit Systems, Inc. ICS-2101 mixer
00937         //   chip, used on Gravis UltraSound cards.
00938         //
00939         //   Block diagram:
00940         //                                    port #
00941         //                                       0 +----+
00942         //    Mic in (Right/Left)        -->--->---|    |
00943         //                                       1 |    |          amp --->---- amp out
00944         //    Line in (Right/Left)       -->--->---|    |           |
00945         //                                       2 |    |           |
00946         //    CD in (Right/Left)         -->--->---|    |--->---+---+----->---- line out
00947         //                                       3 |    |       |
00948         //    GF1 Out (Right/Left)       -->--->---|    |       |
00949         //                                       4 |    |       |
00950         //    Unused (Right/Left)        -->--->---|    |       |
00951         //                                         +----+       v
00952         //                                       ICS 2101       |
00953         //                                                      |
00954         //               To GF1 Sample Input ---<---------------+
00955         //
00956         //    Master output volume: mixer channel #5
00957         enum {
00958                 MIC_IN_PORT=0,
00959                 LINE_IN_PORT=1,
00960                 CD_IN_PORT=2,
00961                 GF1_OUT_PORT=3,
00962                 UNUSED_PORT=4,
00963                 MASTER_OUTPUT_PORT=5
00964         };
00965 public:
00966         gus_ICS2101() {
00967         }
00968 public:
00969         void addressWrite(uint8_t addr) {
00970                 addr_attenuator = (addr >> 3) & 7;
00971                 addr_control = addr & 7;
00972         }
00973         void dataWrite(uint8_t val) {
00974                 LOG(LOG_MISC,LOG_DEBUG)("GUS ICS-2101 Mixer Data Write val=%02xh to attensel=%u(%s) ctrlsel=%u(%s)",
00975                         (int)val,
00976                         addr_attenuator,attenuatorName(addr_attenuator),
00977                         addr_control,controlName(addr_control));
00978 
00979                 if (addr_control & 2) { // attenuator NTS: Only because an existing ICS patch for DOSBox does it this way... does hardware do it this way?
00980                         mixpair[addr_attenuator].setAttenuation(addr_control&1,val);
00981                         mixpair[addr_attenuator].debugPrintMixer(attenuatorName(addr_attenuator));
00982                         updateVolPair(addr_attenuator);
00983                 }
00984                 else if (addr_control & 4) { // pan/balance
00985                         mixpair[addr_attenuator].Panning = val & 0xF;
00986                         // FIXME: Does the panning take effect immediately, or does the chip require the DOS program
00987                         //        to write attenuation again to apply the panning?
00988                 }
00989                 else {
00990                         mixpair[addr_attenuator].setControl(addr_control&1,val);
00991                 }
00992         }
00993         const char *attenuatorName(const uint8_t c) const {
00994                 switch (c) {
00995                         case 0: return "Mic in";
00996                         case 1: return "Line in";
00997                         case 2: return "CD in";
00998                         case 3: return "GF1 out";
00999                         case 4: return "Pair 5, unused";
01000                         case 5: return "Master output";
01001                 };
01002 
01003                 return "?";
01004         }
01005         const char *controlName(const uint8_t c) const {
01006                 switch (c) {
01007                         case 0: return "Control Left";          // 000
01008                         case 1: return "Control Right";         // 001
01009                         case 2: return "Attenuator Left";       // 010
01010                         case 3: return "Attenuator Right";      // 011
01011                         case 4: case 5:                         // 10x
01012                                 return "Pan/Balance";
01013                 };
01014 
01015                 return "?";
01016         }
01017         void updateVolPair(unsigned int pair) {
01018                 if (pair >= MASTER_OUTPUT_PORT) {
01019                         // master volume changes everyone else. do it, through 1 level of recursion.
01020                         for (unsigned int i=0;i < MASTER_OUTPUT_PORT;i++)
01021                                 updateVolPair(i);
01022                 }
01023                 else {
01024                         float m[2];
01025 
01026                         assert(gus_chan != NULL);
01027 
01028                         // copy not just attenuation but modify according to master volume
01029                         for (unsigned int ch=0;ch < 2;ch++) {
01030                                 volpair[pair].AttenDb[ch] = mixpair[pair].AttenDb[ch] + mixpair[MASTER_OUTPUT_PORT].AttenDb[ch];
01031                                 m[ch] = powf(10.0f,volpair[pair].AttenDb[ch]/20.0f);
01032                         }
01033 
01034                         if (pair == GF1_OUT_PORT)
01035                                 gus_chan->SetVolume(m[0],m[1]);
01036                 }
01037         }
01038 public:
01039         struct mixcontrol {
01040         public:
01041                 mixcontrol() {
01042                         Panning = 8;
01043                         Control[0] = 0x01;
01044                         Control[1] = 0x02;
01045                         MapControl[0] = 0x01;
01046                         MapControl[1] = 0x02;
01047                         setAttenuation(0,0x7F); // FIXME: Because we want DOSBox to come up as if ULTRINIT/ULTRAMIX were run to configure the mixer
01048                         setAttenuation(1,0x7F);
01049                 }
01050         public:
01051                 // gain() taken from an existing patch
01052                 float gain(Bit8u val) {  // in 0-127, out -90 to 0db, min to max
01053                         float gain=(127-val)*-0.5;
01054                         if(val<16) for(int i=0;i<(16-val);i++) gain+=-0.5-.13603*(i+1); // increasing rate of change, based on datasheet graph 
01055                         return gain;
01056                 }
01057                 // end borrow
01058                 void setControl(const unsigned int channel,const Bit8u val) {
01059                         Control[channel] = val;
01060                         updateMapControl();
01061                 }
01062                 void updateMapControl() {
01063                         /* control mode according to Left control register, according to datasheet */
01064                         switch (Control[0]&0xE) {
01065                                 case 0: case 2: // normal mode
01066                                         MapControl[0] = Control[0]&3;
01067                                         MapControl[1] = Control[1]&3;
01068                                         break;
01069                                 case 4: // stereo (normal or reversed)
01070                                         MapControl[0] = (Control[0]&1) ? 1 : 2; // left -> left or left -> right if swapped
01071                                         MapControl[1] = (Control[0]&1) ? 2 : 1; // right -> right or right -> left if swapped
01072                                         break;
01073                                 case 6: // Mono
01074                                         MapControl[0] = 1; // Is this right??
01075                                         MapControl[1] = 2; // Is this right??
01076                                         break;
01077                                 case 8: case 12: // Balance
01078                                         MapControl[0] = (Control[0]&1) ? 1 : 2; // left -> left or left -> right if swapped
01079                                         MapControl[1] = (Control[0]&1) ? 2 : 1; // right -> right or right -> left if swapped
01080                                         // fixme: Do we update attenuation to reflect panning? or does the ICS chip need the
01081                                         // DOS program to write the attenuation registers again for the chip to apply balance/panning?
01082                                         break;
01083                                 case 10: case 14: // Pan
01084                                         MapControl[0] = (Control[0]&1) ? 1 : 2; // left -> left or left -> right if swapped
01085                                         MapControl[1] = (Control[0]&1) ? 2 : 1; // right -> right or right -> left if swapped
01086                                         // fixme: Do we update attenuation to reflect panning? or does the ICS chip need the
01087                                         // DOS program to write the attenuation registers again for the chip to apply balance/panning?
01088                                         break;
01089                         }
01090                 }
01091                 void setAttenuation(const unsigned int channel,const Bit8u val) {
01092                         // FIXME: I am only able to test the "normal" mode since that's the only mode used by Gravis's DOS and Windows drivers.
01093                         //        The code below has not been tested in "Stereo" and "Pan/Balance" mode. If any DOS drivers use it, please direct
01094                         //        me to them so I or anyone else can test! ---J.C.
01095 
01096                         if ((Control[0]&0xC) == 0) {
01097                                 Attenuation[channel] = val & 0x7F;
01098                                 AttenDb[channel] = gain(Attenuation[channel]);
01099                         }
01100                         else {
01101                                 // "stereo & balance use left control & gain, copies to right regs" says the Vogons patch I'm studying...
01102                                 Attenuation[0] = Attenuation[1] = val & 0x7F;
01103                                 AttenDb[0] = gain(Attenuation[0]);
01104                                 AttenDb[1] = AttenDb[0];
01105 
01106                                 // taken from the same Vogons patch, except potential access past array fixed
01107                                 if ((Control[0]&0xC) == 8/*Balance/pan mode*/) {
01108                                         static const float pan[16+1] = {-9,-9, -8.5, -6.5,-5.5,-4.5, -3.5,-3,-2.5,-2,-1.5,-1,-.5, 0,0,0,0};
01109                                         AttenDb[0] += pan[Panning];
01110                                         AttenDb[1] += pan[16-Panning];
01111                                 }
01112 
01113                         }
01114                 }
01115                 void debugPrintMixer(const char *name) {
01116                         LOG(LOG_MISC,LOG_DEBUG)("GUS ICS control '%s': %.3fdB %.3fdB",name,AttenDb[0],AttenDb[1]);
01117                 }
01118         public:
01119                 uint8_t         Panning;
01120                 uint8_t         Control[2];
01121                 uint8_t         MapControl[2];
01122                 uint8_t         Attenuation[2];         // 0x00-0x7F where 0x00 is mute (max atten) and 0x7F is full volume
01123                 float           AttenDb[2];             // in decibels
01124         };
01125         struct volpair {
01126 public:
01127                 volpair() {
01128                         AttenDb[0] = AttenDb[1] = 0;
01129                 }
01130 public:
01131                 float           AttenDb[2];
01132                 uint32_t        Fix1616Mult[2];         // linear multiply to apply volume
01133         };
01134 public:
01135         struct mixcontrol       mixpair[8];             // pairs 1-5 and Master
01136         struct volpair          volpair[5];             // pairs 1-5 scaled by master
01137         uint8_t                 addr_attenuator;        // which attenuator is selected
01138         uint8_t                 addr_control;           // which control is selected
01139 } GUS_ICS2101;
01140 
01141 static inline uint8_t read_GF1_mapping_control(const unsigned int ch) {
01142         return GUS_ICS2101.mixpair[gus_ICS2101::GF1_OUT_PORT].MapControl[ch];
01143 }
01144 
01145 /* Gravis Ultrasound MAX Crystal Semiconductor CS4231A emulation */
01146 /* NOTES:
01147  *
01148  *    This 4-port I/O interface, implemented by Crystal Semiconductors, Analog Devices, etc. and used
01149  *    by sound cards in the early 1990s, is the said to be the "standardized" hardware interface of
01150  *    the "Windows Sound System" standard at the time.
01151  *
01152  *    According to an AD1848 datasheet, and a CS4231A datasheet, all I/O ports and indirect registers
01153  *    appear to be the same, with the exception that Crystal Semiconductor adds 16 registers with the
01154  *    "MODE 2" bit.
01155  *
01156  *    Perhaps at some point, we can untie this from GUS emulation and let it exist as it's own C++
01157  *    class that covers CS4231A, AD1848, and other "WSS" chipset emulation on behalf of GUS and SB
01158  *    emulation, much like the OPL3 emulation already present in this source tree for Sound Blaster.
01159  *
01160  */
01161 struct gus_cs4231 {
01162 public:
01163         gus_cs4231() : address(0), mode2(false), ia4(false), trd(false), mce(true), init(false) {
01164         }
01165 public:
01166         void data_write(uint8_t addr,uint8_t val) {
01167 //              LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 write data addr=%02xh val=%02xh",addr,val);
01168 
01169                 switch (addr) {
01170                         case 0x00: /* Left ADC Input Control (I0) */
01171                                 ADCInputControl[0] = val; break;
01172                         case 0x01: /* Right ADC Input Control (I1) */
01173                                 ADCInputControl[1] = val; break;
01174                         case 0x02: /* Left Auxiliary #1 Input Control (I2) */
01175                                 Aux1InputControl[0] = val; break;
01176                         case 0x03: /* Right Auxiliary #1 Input Control (I3) */
01177                                 Aux1InputControl[1] = val; break;
01178                         case 0x06: /* Left DAC Output Control (I6) */
01179                                 DACOutputControl[0] = val; break;
01180                         case 0x07: /* Left DAC Output Control (I7) */
01181                                 DACOutputControl[1] = val; break;
01182                         case 0x0C: /* MODE and ID (I12) */
01183                                 mode2 = (val & 0x40)?1:0; break;
01184                         default:
01185                                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 unhandled data write addr=%02xh val=%02xh",addr,val);
01186                                 break;
01187                 }
01188         }
01189         uint8_t data_read(uint8_t addr) {
01190 //              LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 read data addr=%02xh",addr);
01191 
01192                 switch (addr) {
01193                         case 0x00: /* Left ADC Input Control (I0) */
01194                                 return ADCInputControl[0];
01195                         case 0x01: /* Right ADC Input Control (I1) */
01196                                 return ADCInputControl[1];
01197                         case 0x02: /* Left Auxiliary #1 Input Control (I2) */
01198                                 return Aux1InputControl[0];
01199                         case 0x03: /* Right Auxiliary #1 Input Control (I3) */
01200                                 return Aux1InputControl[1];
01201                         case 0x06: /* Left DAC Output Control (I6) */
01202                                 return DACOutputControl[0];
01203                         case 0x07: /* Left DAC Output Control (I7) */
01204                                 return DACOutputControl[1];
01205                         case 0x0C: /* MODE and ID (I12) */
01206                                 return 0x80 | (mode2 ? 0x40 : 0x00) | 0xA/*1010 codec ID*/;
01207                         default:
01208                                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 unhandled data read addr=%02xh",addr);
01209                                 break;
01210                 }
01211 
01212                 return 0;
01213         }
01214         void playio_data_write(uint8_t val) {
01215                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 Playback I/O write %02xh",val);
01216         }
01217         uint8_t capio_data_read(void) {
01218                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 Capture I/O read");
01219                 return 0;
01220         }
01221         uint8_t status_read(void) {
01222                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 Status read");
01223                 return 0;
01224         }
01225         void iowrite(uint8_t reg,uint8_t val) {
01226 //              LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 write reg=%u val=%02xh",reg,val);
01227 
01228                 if (init) return;
01229 
01230                 switch (reg) {
01231                         case 0x0: /* Index Address Register (R0) */
01232                                 address = val & (mode2 ? 0x1F : 0x0F);
01233                                 trd = (val & 0x20)?1:0;
01234                                 mce = (val & 0x40)?1:0;
01235                                 break;
01236                         case 0x1: /* Index Data Register (R1) */
01237                                 data_write(address,val);
01238                                 break;
01239                         case 0x2: /* Status Register (R2) */
01240                                 LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 attempted write to status register val=%02xh",val);
01241                                 break;
01242                         case 0x3: /* Playback I/O Data Register (R3) */
01243                                 playio_data_write(val);
01244                                 break;
01245                 }
01246         }
01247         uint8_t ioread(uint8_t reg) {
01248 //              LOG(LOG_MISC,LOG_DEBUG)("GUS CS4231 write read=%u",reg);
01249 
01250                 if (init) return 0x80;
01251 
01252                 switch (reg) {
01253                         case 0x0: /* Index Address Register (R0) */
01254                                 return address | (trd?0x20:0x00) | (mce?0x40:0x00) | (init?0x80:0x00);
01255                         case 0x1: /* Index Data Register (R1) */
01256                                 return data_read(address);
01257                         case 0x2: /* Status Register (R2) */
01258                                 return status_read();
01259                         case 0x3: /* Capture I/O Data Register (R3) */
01260                                 return capio_data_read();
01261                 }
01262 
01263                 return 0;
01264         }
01265 public:
01266         uint8_t         address;
01267         bool            mode2; // read CS4231A datasheet for more information
01268         bool            ia4;
01269         bool            trd;
01270         bool            mce;
01271         bool            init;
01272 
01273         uint8_t         ADCInputControl[2];     /* left (I0) and right (I1) ADC Input control. bits 7-6 select source. bit 5 is mic gain. bits 3-0 controls gain. */
01274         uint8_t         Aux1InputControl[2];    /* left (I2) and right (I3) aux. input control. bits 5-0 control gain in 1.5dB steps. bit 7 is mute */
01275         uint8_t         DACOutputControl[2];    /* left (I6) and right (I7) output control attenuation. bits 5-0 control in -1.5dB steps, bit 7 is mute */
01276 } GUS_CS4231;
01277 
01278 static Bitu read_gus_cs4231(Bitu port,Bitu iolen) {
01279     (void)iolen;//UNUSED
01280         if (myGUS.gUltraMAXControl & 0x40/*codec enable*/)
01281                 return GUS_CS4231.ioread((port - GUS_BASE) & 3); // FIXME: UltraMAX allows this to be relocatable
01282 
01283         return 0xFF;
01284 }
01285 
01286 static void write_gus_cs4231(Bitu port,Bitu val,Bitu iolen) {
01287     (void)iolen;//UNUSED
01288         if (myGUS.gUltraMAXControl & 0x40/*codec enable*/)
01289                 GUS_CS4231.iowrite((port - GUS_BASE) & 3,val&0xFF);
01290 }
01291 
01292 static Bitu read_gus(Bitu port,Bitu iolen) {
01293         Bit16u reg16;
01294 
01295     (void)iolen;//UNUSED
01296 //      LOG_MSG("read from gus port %x",port);
01297         switch(port - GUS_BASE) {
01298         case 0x206:
01299                 if (myGUS.clearTCIfPollingIRQStatus) {
01300                         double t = PIC_FullIndex();
01301 
01302                         /* Hack: "Warcraft II" by Blizzard entertainment.
01303                          *
01304                          * If you configure the game to use the Gravis Ultrasound for both music and sound, the GUS support code for digital
01305                          * sound will cause the game to hang if music is playing at the same time within the main menu. The bug is that there
01306                          * is code (in real mode no less) that polls the IRQ status register (2X6) and handles each IRQ event to clear it,
01307                          * however there is no condition to handle clearing the DMA Terminal Count IRQ flag. The routine will not terminate
01308                          * until all bits are cleared, hence, the game hangs after starting a sound effect. Most often, this is visible to
01309                          * the user as causing the game to hang when you click on a button on the main menu.
01310                          *
01311                          * This hack attempts to detect the bug by looking for rapid polling of this register in a short period of time.
01312                          * If detected, we clear the DMA IRQ flag to help the loop terminate so the game continues to run. */
01313                         if (t < (myGUS.lastIRQStatusPollAt + 0.1/*ms*/)) {
01314                                 myGUS.lastIRQStatusPollAt = t;
01315                                 myGUS.lastIRQStatusPollRapidCount++;
01316                                 if (myGUS.clearTCIfPollingIRQStatus && (myGUS.IRQStatus & 0x80) && myGUS.lastIRQStatusPollRapidCount >= 500) {
01317                                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Clearing DMA TC IRQ status, DOS application appears to be stuck");
01318                                         myGUS.lastIRQStatusPollRapidCount = 0;
01319                                         myGUS.lastIRQStatusPollAt = t;
01320                                         myGUS.IRQStatus &= 0x7F;
01321                                         GUS_CheckIRQ();
01322                                 }
01323                         }
01324                         else {
01325                                 myGUS.lastIRQStatusPollAt = t;
01326                                 myGUS.lastIRQStatusPollRapidCount = 0;
01327                         }
01328                 }
01329 
01330                 /* NTS: Contrary to some false impressions, GUS hardware does not report "one at a time", it really is a bitmask.
01331                  *      I had the funny idea you read this register "one at a time" just like reading the IRQ reason bits of the RS-232 port --J.C. */
01332                 return GUS_EffectiveIRQStatus();
01333         case 0x208:
01334                 Bit8u tmptime;
01335                 tmptime = 0;
01336                 if (myGUS.timers[0].reached) tmptime |= (1 << 6);
01337                 if (myGUS.timers[1].reached) tmptime |= (1 << 5);
01338                 if (tmptime & 0x60) tmptime |= (1 << 7);
01339                 if (myGUS.IRQStatus & 0x04) tmptime|=(1 << 2);
01340                 if (myGUS.IRQStatus & 0x08) tmptime|=(1 << 1);
01341                 return tmptime;
01342         case 0x20a:
01343                 return adlib_commandreg;
01344         case 0x20f:
01345                 if (gus_type >= GUS_MAX || gus_ics_mixer)
01346                         return 0x02; /* <- FIXME: What my GUS MAX returns. What does this mean? */
01347                 return ~0ul; // should not happen
01348         case 0x302:
01349                 return myGUS.gRegSelectData;
01350         case 0x303:
01351                 return myGUS.gRegSelectData;
01352         case 0x304:
01353                 if (iolen==2) reg16 = ExecuteReadRegister() & 0xffff;
01354                 else reg16 = ExecuteReadRegister() & 0xff;
01355 
01356                 if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01357                         myGUS.gRegSelectData = reg16 & 0xFF;
01358 
01359                 return reg16;
01360         case 0x305:
01361                 reg16 = ExecuteReadRegister() >> 8;
01362 
01363                 if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01364                         myGUS.gRegSelectData = reg16 & 0xFF;
01365 
01366                 return reg16;
01367         case 0x307:
01368                 if(myGUS.gDramAddr < myGUS.memsize) {
01369                         return GUSRam[myGUS.gDramAddr];
01370                 } else {
01371                         return 0;
01372                 }
01373         case 0x306:
01374         case 0x706:
01375                 if (gus_type >= GUS_MAX)
01376                         return 0x0B; /* UltraMax with CS4231 codec */
01377                 else if (gus_ics_mixer)
01378                         return 0x06; /* revision 3.7+ with ICS-2101 mixer */
01379                 else
01380                         return 0xFF;
01381                 break;
01382         default:
01383 #if LOG_GUS
01384                 LOG_MSG("Read GUS at port 0x%x", port);
01385 #endif
01386                 break;
01387         }
01388 
01389         return 0xff;
01390 }
01391 
01392 
01393 static void write_gus(Bitu port,Bitu val,Bitu iolen) {
01394 //      LOG_MSG("Write gus port %x val %x",port,val);
01395         switch(port - GUS_BASE) {
01396         case 0x200:
01397                 myGUS.gRegControl = 0;
01398                 myGUS.mixControl = (Bit8u)val;
01399                 myGUS.ChangeIRQDMA = true;
01400                 return;
01401         case 0x208:
01402                 adlib_commandreg = (Bit8u)val;
01403                 break;
01404         case 0x209:
01405 //TODO adlib_commandreg should be 4 for this to work else it should just latch the value
01406                 if (val & 0x80) {
01407                         myGUS.timers[0].reached=false;
01408                         myGUS.timers[1].reached=false;
01409                         return;
01410                 }
01411                 myGUS.timers[0].masked=(val & 0x40)>0;
01412                 myGUS.timers[1].masked=(val & 0x20)>0;
01413                 if (val & 0x1) {
01414                         if (!myGUS.timers[0].running) {
01415                                 PIC_AddEvent(GUS_TimerEvent,myGUS.timers[0].delay,0);
01416                                 myGUS.timers[0].running=true;
01417                         }
01418                 } else myGUS.timers[0].running=false;
01419                 if (val & 0x2) {
01420                         if (!myGUS.timers[1].running) {
01421                                 PIC_AddEvent(GUS_TimerEvent,myGUS.timers[1].delay,1);
01422                                 myGUS.timers[1].running=true;
01423                         }
01424                 } else myGUS.timers[1].running=false;
01425                 break;
01426 //TODO Check if 0x20a register is also available on the gus like on the interwave
01427         case 0x20b:
01428                 if (!myGUS.ChangeIRQDMA) break;
01429                 myGUS.ChangeIRQDMA=false;
01430 
01431                 if (myGUS.gRegControl == 6) {
01432                         /* Jumper register:
01433                          *
01434                          * 7: reserved
01435                          * 6: reserved
01436                          * 5: reserved
01437                          * 4: reserved
01438                          * 3: reserved
01439                          * 2: enable joystick port decode
01440                          * 1: enable midi port address decode
01441                          * 0: reserved */
01442                         /* TODO: */
01443                         LOG(LOG_MISC,LOG_DEBUG)("GUS: DOS application wrote to 2XB register control number 0x06 (Jumper) val=%02xh",(int)val);
01444                 }
01445                 else if (myGUS.gRegControl == 5) {
01446                         /* write a 0 to clear IRQs on power up (?) */
01447                         LOG(LOG_MISC,LOG_DEBUG)("GUS: DOS application wrote to 2XB register control number 0x05 (Clear IRQs) val=%02xh",(int)val);
01448                 }
01449                 else if (myGUS.gRegControl == 0) {
01450                         if (myGUS.mixControl & 0x40) {
01451                                 // GUS SDK: IRQ Control Register
01452                                 //     Channel 1 GF1 IRQ selector (bits 2-0)
01453                                 //       0=reserved, do not use
01454                                 //       1=IRQ2
01455                                 //       2=IRQ5
01456                                 //       3=IRQ3
01457                                 //       4=IRQ7
01458                                 //       5=IRQ11
01459                                 //       6=IRQ12
01460                                 //       7=IRQ15
01461                                 //     Channel 2 MIDI IRQ selector (bits 5-3)
01462                                 //       0=no interrupt
01463                                 //       1=IRQ2
01464                                 //       2=IRQ5
01465                                 //       3=IRQ3
01466                                 //       4=IRQ7
01467                                 //       5=IRQ11
01468                                 //       6=IRQ12
01469                                 //       7=IRQ15
01470                                 //     Combine both IRQs using channel 1 (bit 6)
01471                                 //     Reserved (bit 7)
01472                                 //
01473                                 //     "If both channels are sharing an IRQ, channel 2's IRQ must be set to 0 and turn on bit 6. A
01474                                 //      bus conflict will occur if both latches are programmed with the same IRQ #."
01475                                 if (irqtable[val & 0x7] != 0)
01476                                         myGUS.irq1 = irqtable[val & 0x7];
01477 
01478                                 if (val & 0x40) // "Combine both IRQs"
01479                                         myGUS.irq2 = myGUS.irq1;
01480                                 else if (((val >> 3) & 7) != 0)
01481                                         myGUS.irq2 = irqtable[(val >> 3) & 0x7];
01482 
01483                                 LOG(LOG_MISC,LOG_DEBUG)("GUS IRQ reprogrammed: GF1 IRQ %d, MIDI IRQ %d",(int)myGUS.irq1,(int)myGUS.irq2);
01484 
01485                 gus_warn_irq_conflict = (!(val & 0x40) && (val & 7) == ((val >> 3) & 7));
01486                         } else {
01487                                 // GUS SDK: DMA Control Register
01488                                 //     Channel 1 (bits 2-0)
01489                                 //       0=NO DMA
01490                                 //       1=DMA1
01491                                 //       2=DMA3
01492                                 //       3=DMA5
01493                                 //       4=DMA6
01494                                 //       5=DMA7
01495                                 //       6=?
01496                                 //       7=?
01497                                 //     Channel 2 (bits 5-3)
01498                                 //       0=NO DMA
01499                                 //       1=DMA1
01500                                 //       2=DMA3
01501                                 //       3=DMA5
01502                                 //       4=DMA6
01503                                 //       5=DMA7
01504                                 //       6=?
01505                                 //       7=?
01506                                 //     Combine both DMA channels using channel 1 (bit 6)
01507                                 //     Reserved (bit 7)
01508                                 //
01509                                 //     "If both channels are sharing an DMA, channel 2's DMA must be set to 0 and turn on bit 6. A
01510                                 //      bus conflict will occur if both latches are programmed with the same DMA #."
01511 
01512                                 // NTS: This emulation does not use the second DMA channel... yet... which is why we do not bother
01513                                 //      unregistering and reregistering the second DMA channel.
01514 
01515                                 GetDMAChannel(myGUS.dma1)->Register_Callback(0); // FIXME: On DMA conflict this could mean kicking other devices off!
01516 
01517                                 // NTS: Contrary to an earlier commit, DMA channel 0 is not a valid choice
01518                                 if (dmatable[val & 0x7] != 0)
01519                                         myGUS.dma1 = dmatable[val & 0x7];
01520 
01521                                 if (val & 0x40) // "Combine both DMA channels"
01522                                         myGUS.dma2 = myGUS.dma1;
01523                                 else if (dmatable[(val >> 3) & 0x7] != 0)
01524                                         myGUS.dma2 = dmatable[(val >> 3) & 0x7];
01525 
01526                                 GetDMAChannel(myGUS.dma1)->Register_Callback(GUS_DMA_Callback);
01527 
01528                                 LOG(LOG_MISC,LOG_DEBUG)("GUS DMA reprogrammed: DMA1 %d, DMA2 %d",(int)myGUS.dma1,(int)myGUS.dma2);
01529 
01530                                 // NTS: The Windows 3.1 Gravis Ultrasound drivers will program the same DMA channel into both without setting the "combining" bit,
01531                                 //      even though their own SDK says not to, when Windows starts up. But it then immediately reprograms it normally, so no bus
01532                                 //      conflicts actually occur. Strange.
01533                                 gus_warn_dma_conflict = (!(val & 0x40) && (val & 7) == ((val >> 3) & 7));
01534                         }
01535                 }
01536                 else {
01537                         LOG(LOG_MISC,LOG_DEBUG)("GUS warning: Port 2XB register control %02xh written (unknown control reg) val=%02xh",(int)myGUS.gRegControl,(int)val);
01538                 }
01539                 break;
01540         case 0x20f:
01541                 if (gus_type >= GUS_MAX || gus_ics_mixer) {
01542                         myGUS.gRegControl = val;
01543                         myGUS.ChangeIRQDMA = true;
01544                 }
01545                 break;
01546         case 0x302:
01547                 myGUS.gCurChannel = val & 31;
01548                 if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01549                         myGUS.gRegSelectData = (Bit8u)val;
01550 
01551                 curchan = guschan[myGUS.gCurChannel];
01552                 break;
01553         case 0x303:
01554                 myGUS.gRegSelect = myGUS.gRegSelectData = (Bit8u)val;
01555                 myGUS.gRegData = 0;
01556                 break;
01557         case 0x304:
01558                 if (iolen==2) {
01559                         if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01560                                 myGUS.gRegSelectData = val & 0xFF;
01561 
01562                         myGUS.gRegData=(Bit16u)val;
01563                         ExecuteGlobRegister();
01564                 } else {
01565                         if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01566                                 myGUS.gRegSelectData = val;
01567 
01568                         myGUS.gRegData = (Bit16u)val;
01569                 }
01570                 break;
01571         case 0x305:
01572                 if (gus_type < GUS_INTERWAVE) // Versions prior to the Interwave will reflect last I/O to 3X2-3X5 when read back from 3X3
01573                         myGUS.gRegSelectData = val;
01574 
01575                 myGUS.gRegData = (Bit16u)((0x00ff & myGUS.gRegData) | val << 8);
01576                 ExecuteGlobRegister();
01577                 break;
01578         case 0x307:
01579                 if(myGUS.gDramAddr < myGUS.memsize) GUSRam[myGUS.gDramAddr] = (Bit8u)val;
01580                 break;
01581         case 0x306:
01582         case 0x706:
01583                 if (gus_type >= GUS_MAX) {
01584                         /* Ultramax control register:
01585                          *
01586                          * bit 7: reserved
01587                          * bit 6: codec enable
01588                          * bit 5: playback channel type (1=16-bit 0=8-bit)
01589                          * bit 4: capture channel type (1=16-bit 0=8-bit)
01590                          * bits 3-0: Codec I/O port address decode bits 7-4.
01591                          *
01592                          * For example, to put the CS4231 codec at port 0x34C, and enable the codec, write 0x44 to this register.
01593                          * If you want to move the codec to base I/O port 0x32C, write 0x42 here. */
01594                         myGUS.gUltraMAXControl = val;
01595 
01596                         if (val & 0x40) {
01597                                 if ((val & 0xF) != ((port >> 4) & 0xF))
01598                                         LOG(LOG_MISC,LOG_WARN)("GUS WARNING: DOS application is attempting to relocate the CS4231 codec, which is not supported");
01599                         }
01600                 }
01601                 else if (gus_ics_mixer) {
01602                         if ((port - GUS_BASE) == 0x306)
01603                                 GUS_ICS2101.dataWrite(val&0xFF);
01604                         else if ((port - GUS_BASE) == 0x706)
01605                                 GUS_ICS2101.addressWrite(val&0xFF);
01606                 }
01607                 break;
01608         default:
01609 #if LOG_GUS
01610                 LOG_MSG("Write GUS at port 0x%x with %x", port, val);
01611 #endif
01612                 break;
01613         }
01614 }
01615 
01616 static Bitu GUS_Master_Clock = 617400; /* NOTE: This is 1000000Hz / 1.619695497. Seems to be a common base rate within the hardware. */
01617 static Bitu GUS_DMA_Event_transfer = 16; /* DMA words (8 or 16-bit) per interval */
01618 static Bitu GUS_DMA_Events_per_sec = 44100 / 4; /* cheat a little, to improve emulation performance */
01619 static double GUS_DMA_Event_interval = 1000.0 / GUS_DMA_Events_per_sec;
01620 static double GUS_DMA_Event_interval_init = 1000.0 / 44100;
01621 static bool GUS_DMA_Active = false;
01622 
01623 void GUS_Update_DMA_Event_transfer() {
01624         /* NTS: From the GUS SDK, bits 3-4 of DMA Control divide the ISA DMA transfer rate down from "approx 650KHz".
01625          *      Bits 3-4 are documented as "DMA Rate divisor" */
01626         GUS_DMA_Event_transfer = GUS_Master_Clock / GUS_DMA_Events_per_sec / (Bitu)(((Bitu)(myGUS.DMAControl >> 3u) & 3u) + 1u);
01627         GUS_DMA_Event_transfer &= ~1u; /* make sure it's word aligned in case of 16-bit PCM */
01628         if (GUS_DMA_Event_transfer == 0) GUS_DMA_Event_transfer = 2;
01629 }
01630 
01631 void GUS_DMA_Event_Transfer(DmaChannel *chan,Bitu dmawords) {
01632         Bitu dmaaddr = (Bitu)(myGUS.dmaAddr << 4ul) + (Bitu)myGUS.dmaAddrOffset;
01633         Bitu dmalimit = myGUS.memsize;
01634         int step = 0,docount = 0;
01635         bool dma16xlate;
01636         Bitu holdAddr;
01637 
01638         // FIXME: What does the GUS do if the DMA address goes beyond the end of memory?
01639 
01640         /* is this a DMA transfer where the GUS memory address is to be translated for 16-bit PCM?
01641          * Note that there is plenty of code out there that transfers 16-bit PCM with 8-bit DMA,
01642          * and such transfers DO NOT involve the memory address translation.
01643          *
01644          * MODE    XLATE?    NOTE
01645          * 0x00    NO        8-bit PCM, 8-bit DMA (Most DOS programs)
01646          * 0x04    DEPENDS   8-bit PCM, 16-bit DMA (Star Control II, see comments below)
01647          * 0x40    NO        16-bit PCM, 8-bit DMA (Windows 3.1, Quake, for 16-bit PCM over 8-bit DMA)
01648          * 0x44    YES       16-bit PCM, 16-bit DMA (Windows 3.1, Quake, for 16-bit PCM over 16-bit DMA)
01649          *
01650          * Mode 0x04 is marked DEPENDS. It DEPENDS on whether the assigned DMA channel is 8-bit (NO) or 16-bit (YES).
01651          * Mode 0x04 does not appear to be used by any other DOS application or Windows drivers, only by an erratic
01652          * bug in Star Control II. FIXME: But, what does REAL hardware do? Drag out the old Pentium 100MHz with the
01653          * GUS classic and test! --J.C.
01654          *
01655          * Star Control II has a bug where, if the GUS DMA channel is 8-bit (DMA channel 0-3), it will upload
01656          * it's samples to GUS RAM, one DMA transfer per sample, and sometimes set bit 2. Setting bit 2 incorrectly
01657          * tells the GUS it's a 16-bit wide DMA transfer when the DMA channel is 8-bit. But, if the DMA channel is
01658          * 16-bit (DMA channel 5-7), Star Control II will correctly set bit 2 in all cases and samples will
01659          * transfer correctly to GUS RAM.
01660          * */
01661 
01662         /* FIXME: So, if the GUS DMA channel is 8-bit and Star Control II writes mode 0x04 (8-bit PCM, 16-bit DMA), what does the GF1 do?
01663          *        I'm guessing so far that something happens within the GF1 to transfer as 8-bit anyway, clearly the developers of Star Control II
01664          *        did not hear any audible sign that an invalid DMA control was being used. Perhaps the hardware engineers of the GF1 figured
01665          *        out that case and put something in the silicon to ignore the invalid DMA control state. I won't have any answers until
01666          *        I pull out an old Pentium box with a GUS classic and check. --J.C.
01667          *
01668          *        DMA transfers noted by Star Control II that are the reason for this hack (gusdma=1):
01669          *
01670          *        LOG:  157098507 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01671          *        LOG:  157098507 DEBUG MISC:GUS DMA transfer 1981 bytes, GUS RAM address 0x0 8-bit DMA 8-bit PCM (ctrl=0x21)
01672          *        LOG:  157098507 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01673          *        LOG:  157100331 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01674          *        LOG:  157100331 DEBUG MISC:GUS DMA transfer 912 bytes, GUS RAM address 0x7c0 8-bit DMA 8-bit PCM (ctrl=0x21)
01675          *        LOG:  157100331 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01676          *        LOG:  157100470 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x25
01677          *        LOG:  157100470 DEBUG MISC:GUS DMA transfer 1053 bytes, GUS RAM address 0xb50 16-bit DMA 8-bit PCM (ctrl=0x25)    <-- What?
01678          *        LOG:  157100470 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x25
01679          *        LOG:  157102251 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01680          *        LOG:  157102251 DEBUG MISC:GUS DMA transfer 1597 bytes, GUS RAM address 0xf80 8-bit DMA 8-bit PCM (ctrl=0x21)
01681          *        LOG:  157102251 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01682          *        LOG:  157104064 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01683          *        LOG:  157104064 DEBUG MISC:GUS DMA transfer 2413 bytes, GUS RAM address 0x15c0 8-bit DMA 8-bit PCM (ctrl=0x21)
01684          *        LOG:  157104064 DEBUG MISC:GUS DMA: terminal count reached. DMAControl=0x21
01685          *
01686          *        (end list)
01687          *
01688          *        Noted: Prior to this hack, the samples played by Star Control II sounded more random and often involved leftover
01689          *               sample data in GUS RAM, where with this fix, the music now sounds identical to what is played when using
01690          *               it's Sound Blaster support. */
01691         if (myGUS.dma1 < 4/*8-bit DMA channel*/ && (myGUS.DMAControl & 0x44) == 0x04/*8-bit PCM, 16-bit DMA*/)
01692                 dma16xlate = false; /* Star Control II hack: 8-bit PCM, 8-bit DMA, ignore the bit that says it's 16-bit wide */
01693         else
01694                 dma16xlate = (myGUS.DMAControl & 0x4) ? true : false;
01695 
01696         if (dma16xlate) {
01697                 // 16-bit wide DMA. The GUS SDK specifically mentions that 16-bit DMA is translated
01698                 // to GUS RAM the same way you translate the play pointer. Eugh. But this allows
01699                 // older demos to work properly even if you set the GUS DMA to a 16-bit channel (5)
01700                 // instead of the usual 8-bit channel (1).
01701                 holdAddr = dmaaddr & 0xc0000L;
01702                 dmaaddr = dmaaddr & 0x1ffffL;
01703                 dmaaddr = dmaaddr << 1;
01704                 dmaaddr = (holdAddr | dmaaddr);
01705                 dmalimit = ((dmaaddr & 0xc0000L) | 0x3FFFFL) + 1;
01706         }
01707 
01708         if (dmaaddr < dmalimit)
01709                 docount = dmalimit - dmaaddr;
01710 
01711         docount /= (chan->DMA16+1);
01712         if (docount > (chan->currcnt+1)) docount = chan->currcnt+1;
01713         if ((Bitu)docount > dmawords) docount = dmawords;
01714 
01715         // hack: some programs especially Gravis Ultrasound MIDI playback like to upload by DMA but never clear the DMA TC flag on the DMA controller.
01716         bool saved_tcount = chan->tcount;
01717         chan->tcount = false;
01718 
01719         if (docount > 0) {
01720                 if ((myGUS.DMAControl & 0x2) == 0) {
01721                         Bitu read=(Bitu)chan->Read((Bitu)docount,&GUSRam[dmaaddr]);
01722                         //Check for 16 or 8bit channel
01723                         read*=(chan->DMA16+1u);
01724                         if((myGUS.DMAControl & 0x80) != 0) {
01725                                 //Invert the MSB to convert twos compliment form
01726                                 Bitu i;
01727                                 if((myGUS.DMAControl & 0x40) == 0) {
01728                                         // 8-bit data
01729                                         for(i=dmaaddr;i<(dmaaddr+read);i++) GUSRam[i] ^= 0x80;
01730                                 } else {
01731                                         // 16-bit data
01732                                         for(i=dmaaddr+1;i<(dmaaddr+read);i+=2) GUSRam[i] ^= 0x80;
01733                                 }
01734                         }
01735 
01736                         step = read;
01737                 } else {
01738                         //Read data out of UltraSound
01739                         Bitu wd = (Bitu)chan->Write((Bitu)docount,&GUSRam[dmaaddr]);
01740                         //Check for 16 or 8bit channel
01741                         wd*=(chan->DMA16+1u);
01742 
01743                         step = wd;
01744                 }
01745         }
01746 
01747         LOG(LOG_MISC,LOG_DEBUG)("GUS DMA transfer %lu bytes, GUS RAM address 0x%lx %u-bit DMA %u-bit PCM (ctrl=0x%02x) tcount=%u",
01748                 (unsigned long)step,(unsigned long)dmaaddr,myGUS.DMAControl & 0x4 ? 16 : 8,myGUS.DMAControl & 0x40 ? 16 : 8,myGUS.DMAControl,chan->tcount);
01749 
01750         if (step > 0) {
01751                 dmaaddr += (unsigned int)step;
01752 
01753                 if (dma16xlate) {
01754                         holdAddr = dmaaddr & 0xc0000L;
01755                         dmaaddr = dmaaddr & 0x3ffffL;
01756                         dmaaddr = dmaaddr >> 1;
01757                         dmaaddr = (holdAddr | dmaaddr);
01758                 }
01759 
01760                 myGUS.dmaAddr = dmaaddr >> 4;
01761                 myGUS.dmaAddrOffset = dmaaddr & 0xF;
01762         }
01763 
01764         if (chan->tcount) {
01765                 LOG(LOG_MISC,LOG_DEBUG)("GUS DMA transfer hit Terminal Count, setting DMA TC IRQ pending");
01766 
01767                 /* Raise the TC irq, and stop DMA */
01768                 myGUS.IRQStatus |= 0x80;
01769                 saved_tcount = true;
01770                 GUS_CheckIRQ();
01771                 GUS_StopDMA();
01772         }
01773 
01774         chan->tcount = saved_tcount;
01775 }
01776 
01777 void GUS_DMA_Event(Bitu val) {
01778     (void)val;//UNUSED
01779         DmaChannel *chan = GetDMAChannel(myGUS.dma1);
01780         if (chan == NULL) {
01781                 LOG(LOG_MISC,LOG_DEBUG)("GUS DMA event: DMA channel no longer exists, stopping DMA transfer events");
01782                 GUS_DMA_Active = false;
01783                 return;
01784         }
01785 
01786         if (chan->masked) {
01787                 LOG(LOG_MISC,LOG_DEBUG)("GUS: Stopping DMA transfer interval, DMA masked=%u",chan->masked?1:0);
01788                 GUS_DMA_Active = false;
01789                 return;
01790         }
01791 
01792         if (!(myGUS.DMAControl & 0x01/*DMA enable*/)) {
01793                 LOG(LOG_MISC,LOG_DEBUG)("GUS DMA event: DMA control 'enable DMA' bit was reset, stopping DMA transfer events");
01794                 GUS_DMA_Active = false;
01795                 return;
01796         }
01797 
01798         LOG(LOG_MISC,LOG_DEBUG)("GUS DMA event: max %u DMA words. DMA: tc=%u mask=%u cnt=%u",
01799                 (unsigned int)GUS_DMA_Event_transfer,
01800                 chan->tcount?1:0,
01801                 chan->masked?1:0,
01802                 chan->currcnt+1);
01803         GUS_DMA_Event_Transfer(chan,GUS_DMA_Event_transfer);
01804 
01805         if (GUS_DMA_Active) {
01806                 /* keep going */
01807                 PIC_AddEvent(GUS_DMA_Event,GUS_DMA_Event_interval);
01808         }
01809 }
01810 
01811 void GUS_StopDMA() {
01812         if (GUS_DMA_Active)
01813                 LOG(LOG_MISC,LOG_DEBUG)("GUS: Stopping DMA transfer interval");
01814 
01815         PIC_RemoveEvents(GUS_DMA_Event);
01816         GUS_DMA_Active = false;
01817 }
01818 
01819 void GUS_StartDMA() {
01820         if (!GUS_DMA_Active) {
01821                 GUS_DMA_Active = true;
01822                 LOG(LOG_MISC,LOG_DEBUG)("GUS: Starting DMA transfer interval");
01823                 PIC_AddEvent(GUS_DMA_Event,GUS_DMA_Event_interval_init);
01824 
01825         if (gus_warn_dma_conflict)
01826             LOG(LOG_MISC,LOG_WARN)(
01827                 "GUS warning: Both DMA channels set to the same channel WITHOUT combining! "
01828                 "This is documented to cause bus conflicts on real hardware");
01829     }
01830 }
01831 
01832 static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event) {
01833     (void)chan;//UNUSED
01834         if (event == DMA_UNMASKED) {
01835                 LOG(LOG_MISC,LOG_DEBUG)("GUS: DMA unmasked");
01836                 if (myGUS.DMAControl & 0x01/*DMA enable*/) GUS_StartDMA();
01837         }
01838         else if (event == DMA_MASKED) {
01839                 LOG(LOG_MISC,LOG_DEBUG)("GUS: DMA masked. Perhaps it will stop the DMA transfer event.");
01840         }
01841 }
01842 
01843 static void GUS_CallBack(Bitu len) {
01844         memset(&MixTemp,0,len*8);
01845         Bitu i;
01846         Bit16s * buf16 = (Bit16s *)MixTemp;
01847         Bit32s * buf32 = (Bit32s *)MixTemp;
01848 
01849         if ((GUS_reset_reg & 0x01) == 0x01) {
01850                 for(i=0;i<myGUS.ActiveChannels;i++)
01851                         guschan[i]->generateSamples(buf32,len);
01852         }
01853 
01854     // FIXME: I wonder if the GF1 chip DAC had more than 16 bits precision
01855     //        to render louder than 100% volume without clipping, and if so,
01856     //        how many extra bits?
01857     //
01858     //        If not, then perhaps clipping and saturation were not a problem
01859     //        unless the volume was set to maximum?
01860     //
01861     //        Time to pull out the GUS MAX and test this theory: what happens
01862     //        if you play samples that would saturate at maximum volume at 16-bit
01863     //        precision? Does it audibly clip or is there some headroom like some
01864     //        sort of 17-bit DAC?
01865     //
01866     //        One way to test is to play a sample on one channel while another
01867     //        channel is set to play a single sample at maximum volume (to see
01868     //        if it makes the audio grungy like a waveform railed to one side).
01869     //
01870     //        Past experience with GUS cards says that at full volume their line
01871     //        out jacks can be quite loud when connected to a speaker.
01872     //
01873     //        While improving this code, a better audio compression function
01874     //        could be implemented that does proper envelope tracking and volume
01875     //        control for better results than this.
01876     //
01877     //        --J.C.
01878 
01879     for(i=0;i<len*2;i++) {
01880         Bit32s sample=((buf32[i] >> 13)*AutoAmp)>>9;
01881         if (sample>32767) {
01882             sample=32767;
01883             if (enable_autoamp) AutoAmp -= 4; /* dampen faster than recovery */
01884         } else if (sample<-32768) {
01885             sample=-32768;
01886             if (enable_autoamp) AutoAmp -= 4; /* dampen faster than recovery */
01887         }
01888         else if (AutoAmp < 512) {
01889             AutoAmp++; /* recovery back to 100% normal volume */
01890         }
01891 
01892         buf16[i] = (Bit16s)(sample);
01893     }
01894 
01895         gus_chan->AddSamples_s16(len,buf16);
01896         CheckVoiceIrq();
01897 }
01898 
01899 // Generate logarithmic to linear volume conversion tables
01900 static void MakeTables(void) {
01901         int i;
01902         double out = (double)(1 << 13);
01903         for (i=4095;i>=0;i--) {
01904                 vol16bit[i]=(Bit16u)((Bit16s)out);
01905                 out/=1.002709201;               /* 0.0235 dB Steps */
01906         }
01907         /* FIX: DOSBox 0.74 had code here that produced a pantable which
01908          *      had nothing to do with actual panning control variables.
01909          *      Instead it seemed to generate a 16-element map that started
01910          *      at 0, jumped sharply to unity and decayed to 0.
01911          *      The unfortunate result was that stock builds of DOSBox
01912          *      effectively locked Gravis Ultrasound capable programs
01913          *      to monural audio.
01914          *
01915          *      This fix generates the table properly so that they correspond
01916          *      to how much we attenuate the LEFT channel for any given
01917          *      4-bit value of the Panning register (you attenuate the
01918          *      RIGHT channel by looking at element 0xF - (val&0xF)).
01919          *
01920          *      Having made this fix I can finally enjoy old DOS demos
01921          *      in GUS stereo instead of having everything mushed into
01922          *      mono. */
01923         if (gus_fixed_table) {
01924                 for (i=0;i < 16;i++)
01925                         pantable[i] = pantablePDF[i] * 2048u;
01926 
01927                 LOG(LOG_MISC,LOG_DEBUG)("GUS: using accurate (fixed) pantable");
01928         }
01929         else {
01930                 for (i=0;i < 8;i++)
01931                         pantable[i] = 0;
01932                 for (i=8;i < 15;i++)
01933                         pantable[i]=(Bit32u)(-128.0*(log((double)(15-i)/7.0)/log(2.0))*(double)(1 << RAMP_FRACT));
01934 
01935                 /* if the program cranks the pan register all the way, ensure the
01936                  * opposite channel is crushed to silence */
01937                 pantable[15] = 1UL << 30UL;
01938 
01939                 LOG(LOG_MISC,LOG_DEBUG)("GUS: using old (naive) pantable");
01940         }
01941 
01942         LOG(LOG_MISC,LOG_DEBUG)("GUS pantable (attenuation, left to right in dB): hard left -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, center(7) -%.3f, center(8) -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, -%.3f, hard right -%.3f",
01943                 ((double)pantable[0]) / (1 << RAMP_FRACT),
01944                 ((double)pantable[1]) / (1 << RAMP_FRACT),
01945                 ((double)pantable[2]) / (1 << RAMP_FRACT),
01946                 ((double)pantable[3]) / (1 << RAMP_FRACT),
01947                 ((double)pantable[4]) / (1 << RAMP_FRACT),
01948                 ((double)pantable[5]) / (1 << RAMP_FRACT),
01949                 ((double)pantable[6]) / (1 << RAMP_FRACT),
01950                 ((double)pantable[7]) / (1 << RAMP_FRACT),
01951                 ((double)pantable[8]) / (1 << RAMP_FRACT),
01952                 ((double)pantable[9]) / (1 << RAMP_FRACT),
01953                 ((double)pantable[10]) / (1 << RAMP_FRACT),
01954                 ((double)pantable[11]) / (1 << RAMP_FRACT),
01955                 ((double)pantable[12]) / (1 << RAMP_FRACT),
01956                 ((double)pantable[13]) / (1 << RAMP_FRACT),
01957                 ((double)pantable[14]) / (1 << RAMP_FRACT),
01958                 ((double)pantable[15]) / (1 << RAMP_FRACT));
01959 }
01960 
01961 class GUS:public Module_base{
01962 private:
01963         IO_ReadHandleObject ReadHandler[12];
01964         IO_WriteHandleObject WriteHandler[12];
01965         IO_ReadHandleObject ReadCS4231Handler[4];
01966         IO_WriteHandleObject WriteCS4231Handler[4];
01967         AutoexecObject autoexecline[3];
01968         MixerObject MixerChan;
01969     bool gus_enable;
01970 public:
01971         GUS(Section* configuration):Module_base(configuration){
01972                 int x;
01973 
01974         gus_enable = false;
01975         if(!IS_EGAVGA_ARCH) return;
01976         Section_prop * section=static_cast<Section_prop *>(configuration);
01977         if(!section->Get_bool("gus")) return;
01978 
01979         gus_enable = true;
01980         memset(&myGUS,0,sizeof(myGUS));
01981         memset(GUSRam,0,1024*1024);
01982 
01983         enable_autoamp = section->Get_bool("autoamp");
01984 
01985                 string s_pantable = section->Get_string("gus panning table");
01986                 if (s_pantable == "default" || s_pantable == "" || s_pantable == "accurate")
01987                         gus_fixed_table = true;
01988                 else if (s_pantable == "old")
01989                         gus_fixed_table = false;
01990                 else
01991                         gus_fixed_table = true;
01992 
01993                 gus_ics_mixer = false;
01994                 string s_gustype = section->Get_string("gustype");
01995                 if (s_gustype == "classic") {
01996                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Classic emulation");
01997                         gus_type = GUS_CLASSIC;
01998                 }
01999                 else if (s_gustype == "classic37") {
02000                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Classic emulation");
02001                         gus_type = GUS_CLASSIC;
02002                         gus_ics_mixer = true;
02003                 }
02004                 else if (s_gustype == "max") {
02005                         // UltraMAX cards do not have the ICS mixer
02006                         LOG(LOG_MISC,LOG_DEBUG)("GUS: MAX emulation");
02007                         gus_type = GUS_MAX;
02008                 }
02009                 else if (s_gustype == "interwave") {
02010                         // Neither do Interwave cards
02011                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Interwave PnP emulation");
02012                         gus_type = GUS_INTERWAVE;
02013                 }
02014                 else {
02015                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Classic emulation by default");
02016                         gus_type = GUS_CLASSIC;
02017                 }
02018 
02019                 myGUS.clearTCIfPollingIRQStatus = section->Get_bool("clear dma tc irq if excess polling");
02020                 if (myGUS.clearTCIfPollingIRQStatus)
02021                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Will clear DMA TC IRQ if excess polling, as instructed");
02022 
02023                 myGUS.gUltraMAXControl = 0;
02024                 myGUS.lastIRQStatusPollRapidCount = 0;
02025                 myGUS.lastIRQStatusPollAt = 0;
02026 
02027                 myGUS.initUnmaskDMA = section->Get_bool("unmask dma");
02028                 if (myGUS.initUnmaskDMA)
02029                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Unmasking DMA at boot time as requested");
02030 
02031                 myGUS.fixed_sample_rate_output = section->Get_bool("gus fixed render rate");
02032                 LOG(LOG_MISC,LOG_DEBUG)("GUS: using %s sample rate output",myGUS.fixed_sample_rate_output?"fixed":"realistic");
02033 
02034                 myGUS.force_master_irq_enable=section->Get_bool("force master irq enable");
02035                 if (myGUS.force_master_irq_enable)
02036                         LOG(LOG_MISC,LOG_DEBUG)("GUS: Master IRQ enable will be forced on as instructed");
02037 
02038                 myGUS.rate=(unsigned int)section->Get_int("gusrate");
02039 
02040         ultradir = section->Get_string("ultradir");
02041 
02042                 x = section->Get_int("gusmemsize");
02043                 if (x >= 0) myGUS.memsize = (unsigned int)x*1024u;
02044                 else myGUS.memsize = 1024u*1024u;
02045 
02046                 if (myGUS.memsize > (1024u*1024u))
02047                         myGUS.memsize = (1024u*1024u);
02048 
02049                 if ((myGUS.memsize&((256u << 10u) - 1u)) != 0)
02050                         LOG(LOG_MISC,LOG_WARN)("GUS emulation warning: %uKB onboard is an unusual value. Usually GUS cards have some multiple of 256KB RAM onboard",myGUS.memsize>>10);
02051 
02052                 LOG(LOG_MISC,LOG_DEBUG)("GUS emulation: %uKB onboard",myGUS.memsize>>10);
02053 
02054                 // FIXME: HUH?? Read the port number and subtract 0x200, then use GUS_BASE
02055                 // in other parts of the code to compare against 0x200 and 0x300? That's confusing. Fix!
02056                 myGUS.portbase = (unsigned int)section->Get_hex("gusbase") - 0x200u;
02057 
02058                 // TODO: so, if the GUS ULTRASND variable actually mentions two DMA and two IRQ channels,
02059                 //       shouldn't we offer the ability to specify them independently? especially when
02060                 //       GUS NMI is completed to the extent that SBOS and MEGA-EM can run within DOSBox?
02061                 int dma_val = section->Get_int("gusdma");
02062                 if ((dma_val<0) || (dma_val>255)) dma_val = 3;  // sensible default
02063 
02064                 int irq_val = section->Get_int("gusirq");
02065                 if ((irq_val<0) || (irq_val>255)) irq_val = 5;  // sensible default
02066 
02067                 myGUS.dma1 = (Bit8u)dma_val;
02068                 myGUS.dma2 = (Bit8u)dma_val;
02069                 myGUS.irq1 = (Bit8u)irq_val;
02070                 myGUS.irq2 = (Bit8u)irq_val;
02071 
02072                 // We'll leave the MIDI interface to the MPU-401 
02073                 // Ditto for the Joystick 
02074                 // GF1 Synthesizer 
02075                 ReadHandler[0].Install(0x302 + GUS_BASE,read_gus,IO_MB);
02076                 WriteHandler[0].Install(0x302 + GUS_BASE,write_gus,IO_MB);
02077         
02078                 WriteHandler[1].Install(0x303 + GUS_BASE,write_gus,IO_MB);
02079                 ReadHandler[1].Install(0x303 + GUS_BASE,read_gus,IO_MB);
02080         
02081                 WriteHandler[2].Install(0x304 + GUS_BASE,write_gus,IO_MB|IO_MW);
02082                 ReadHandler[2].Install(0x304 + GUS_BASE,read_gus,IO_MB|IO_MW);
02083         
02084                 WriteHandler[3].Install(0x305 + GUS_BASE,write_gus,IO_MB);
02085                 ReadHandler[3].Install(0x305 + GUS_BASE,read_gus,IO_MB);
02086         
02087                 ReadHandler[4].Install(0x206 + GUS_BASE,read_gus,IO_MB);
02088         
02089                 WriteHandler[4].Install(0x208 + GUS_BASE,write_gus,IO_MB);
02090                 ReadHandler[5].Install(0x208 + GUS_BASE,read_gus,IO_MB);
02091         
02092                 WriteHandler[5].Install(0x209 + GUS_BASE,write_gus,IO_MB);
02093         
02094                 WriteHandler[6].Install(0x307 + GUS_BASE,write_gus,IO_MB);
02095                 ReadHandler[6].Install(0x307 + GUS_BASE,read_gus,IO_MB);
02096         
02097                 // Board Only 
02098         
02099                 WriteHandler[7].Install(0x200 + GUS_BASE,write_gus,IO_MB);
02100                 ReadHandler[7].Install(0x20A + GUS_BASE,read_gus,IO_MB);
02101                 WriteHandler[8].Install(0x20B + GUS_BASE,write_gus,IO_MB);
02102 
02103                 if (gus_type >= GUS_MAX || gus_ics_mixer/*classic with 3.7 mixer*/) {
02104                         /* "This register is only valid for UltraSound boards that are at or above revision 3.4. It is not valid for boards which
02105                          * have a prior revision number.
02106                          * On 3.4 and above boards, there is a bank of 6 registers that exist at location 2XB. Register 2XF is used to select
02107                          * which one is being talked to." */
02108                         ReadHandler[9].Install(0x20F + GUS_BASE,read_gus,IO_MB);
02109                         WriteHandler[9].Install(0x20F + GUS_BASE,write_gus,IO_MB);
02110 
02111                         /* FIXME: I'm not so sure Interwave PnP cards have this */
02112                         ReadHandler[10].Install(0x306 + GUS_BASE,read_gus,IO_MB); // Revision level
02113                         ReadHandler[11].Install(0x706 + GUS_BASE,read_gus,IO_MB); // Revision level
02114                         WriteHandler[10].Install(0x306 + GUS_BASE,write_gus,IO_MB); // Mixer control
02115                         WriteHandler[11].Install(0x706 + GUS_BASE,write_gus,IO_MB); // Mixer data / GUS UltraMAX Control register
02116                 }
02117                 if (gus_type >= GUS_MAX) {
02118                         LOG(LOG_MISC,LOG_WARN)("GUS caution: CS4231 UltraMax emulation is new and experimental at this time and it is not guaranteed to work.");
02119                         LOG(LOG_MISC,LOG_WARN)("GUS caution: CS4231 UltraMax emulation as it exists now may cause applications to hang or malfunction attempting to play through it.");
02120 
02121                         /* UltraMax has a CS4231 codec at 3XC-3XF */
02122                         /* FIXME: Does the Interwave have a CS4231? */
02123                         for (unsigned int i=0;i < 4;i++) {
02124                                 ReadCS4231Handler[i].Install(0x30C + i + GUS_BASE,read_gus_cs4231,IO_MB);
02125                                 WriteCS4231Handler[i].Install(0x30C + i + GUS_BASE,write_gus_cs4231,IO_MB);
02126                         }
02127                 }
02128         
02129         //      DmaChannels[myGUS.dma1]->Register_TC_Callback(GUS_DMA_TC_Callback);
02130         
02131                 MakeTables();
02132         
02133                 for (Bit8u chan_ct=0; chan_ct<32; chan_ct++) {
02134                         guschan[chan_ct] = new GUSChannels(chan_ct);
02135                 }
02136                 // Register the Mixer CallBack 
02137                 gus_chan=MixerChan.Install(GUS_CallBack,GUS_RATE,"GUS");
02138 
02139                 // FIXME: Could we leave the card in reset state until a fake ULTRINIT runs?
02140                 myGUS.gRegData=0x000/*reset*/;
02141                 GUSReset();
02142 
02143                 if (myGUS.initUnmaskDMA)
02144                         GetDMAChannel(myGUS.dma1)->SetMask(false);
02145 
02146                 gus_chan->Enable(true);
02147 
02148                 GetDMAChannel(myGUS.dma1)->Register_Callback(GUS_DMA_Callback);
02149 
02150                 if (gus_ics_mixer) {
02151                         // pre-set ourself as if ULTRINIT and ULTRAMIX had been run
02152                         GUS_ICS2101.mixpair[gus_ICS2101::MIC_IN_PORT].setAttenuation(0,0x7F);
02153                         GUS_ICS2101.mixpair[gus_ICS2101::MIC_IN_PORT].setAttenuation(1,0x7F);
02154                         GUS_ICS2101.mixpair[gus_ICS2101::LINE_IN_PORT].setAttenuation(0,0x7F);
02155                         GUS_ICS2101.mixpair[gus_ICS2101::LINE_IN_PORT].setAttenuation(1,0x7F);
02156                         GUS_ICS2101.mixpair[gus_ICS2101::CD_IN_PORT].setAttenuation(0,0x7F);
02157                         GUS_ICS2101.mixpair[gus_ICS2101::CD_IN_PORT].setAttenuation(1,0x7F);
02158                         GUS_ICS2101.mixpair[gus_ICS2101::GF1_OUT_PORT].setAttenuation(0,0x7F);
02159                         GUS_ICS2101.mixpair[gus_ICS2101::GF1_OUT_PORT].setAttenuation(1,0x7F);
02160                         GUS_ICS2101.mixpair[gus_ICS2101::MASTER_OUTPUT_PORT].setAttenuation(0,0x7F);
02161                         GUS_ICS2101.mixpair[gus_ICS2101::MASTER_OUTPUT_PORT].setAttenuation(1,0x7F);
02162 
02163                         // master volume update, updates ALL pairs
02164                         GUS_ICS2101.updateVolPair(gus_ICS2101::MASTER_OUTPUT_PORT);
02165                 }
02166         }
02167 
02168     void DOS_Startup() {
02169                 int portat = 0x200+GUS_BASE;
02170 
02171         if (!gus_enable) return;
02172 
02173                 // ULTRASND=Port,DMA1,DMA2,IRQ1,IRQ2
02174                 // [GUS port], [GUS DMA (recording)], [GUS DMA (playback)], [GUS IRQ (playback)], [GUS IRQ (MIDI)]
02175                 ostringstream temp;
02176                 temp << "SET ULTRASND=" << hex << setw(3) << portat << ","
02177                      << dec << (Bitu)myGUS.dma1 << "," << (Bitu)myGUS.dma2 << ","
02178                      << (Bitu)myGUS.irq1 << "," << (Bitu)myGUS.irq2 << ends;
02179                 // Create autoexec.bat lines
02180                 autoexecline[0].Install(temp.str());
02181                 autoexecline[1].Install(std::string("SET ULTRADIR=") + ultradir);
02182 
02183                 if (gus_type >= GUS_MAX) {
02184                         /* FIXME: Does the Interwave have a CS4231? */
02185                         ostringstream temp2;
02186                         temp2 << "SET ULTRA16=" << hex << setw(3) << (0x30C+GUS_BASE) << ","
02187                                 << "0,0,1,0" << ends; // FIXME What do these numbers mean?
02188                         autoexecline[2].Install(temp2.str());
02189                 }
02190     }
02191 
02192     std::string ultradir;
02193 
02194         void DOS_Shutdown() { /* very likely, we're booting into a guest OS where our environment variable has no meaning anymore */
02195                 autoexecline[0].Uninstall();
02196                 autoexecline[1].Uninstall();
02197                 autoexecline[2].Uninstall();
02198         }
02199 
02200         ~GUS() {
02201 #if 0 // FIXME
02202                 if(!IS_EGAVGA_ARCH) return;
02203         
02204                 myGUS.gRegData=0x1;
02205                 GUSReset();
02206                 myGUS.gRegData=0x0;
02207         
02208                 for(Bitu i=0;i<32;i++) {
02209                         delete guschan[i];
02210                 }
02211 
02212                 memset(&myGUS,0,sizeof(myGUS));
02213                 memset(GUSRam,0,1024*1024);
02214 #endif
02215         }
02216 };
02217 
02218 static GUS* test = NULL;
02219 
02220 void GUS_DOS_Shutdown() {
02221         if (test != NULL) test->DOS_Shutdown();
02222 }
02223 
02224 void GUS_ShutDown(Section* /*sec*/) {
02225         if (test != NULL) {
02226                 delete test;    
02227                 test = NULL;
02228         }
02229 }
02230 
02231 void GUS_OnReset(Section *sec) {
02232     (void)sec;//UNUSED
02233         if (test == NULL && !IS_PC98_ARCH) {
02234                 LOG(LOG_MISC,LOG_DEBUG)("Allocating GUS emulation");
02235                 test = new GUS(control->GetSection("gus"));
02236         }
02237 }
02238 
02239 void GUS_DOS_Exit(Section *sec) {
02240     (void)sec;//UNUSED
02241     GUS_DOS_Shutdown();
02242 }
02243 
02244 void GUS_DOS_Boot(Section *sec) {
02245     (void)sec;//UNUSED
02246     if (test != NULL) test->DOS_Startup();
02247 }
02248 
02249 void GUS_Init() {
02250         LOG(LOG_MISC,LOG_DEBUG)("Initializing Gravis Ultrasound emulation");
02251 
02252         AddExitFunction(AddExitFunctionFuncPair(GUS_ShutDown),true);
02253         AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(GUS_OnReset));
02254         AddVMEventFunction(VM_EVENT_DOS_EXIT_BEGIN,AddVMEventFunctionFuncPair(GUS_DOS_Exit));
02255         AddVMEventFunction(VM_EVENT_DOS_SURPRISE_REBOOT,AddVMEventFunctionFuncPair(GUS_DOS_Exit));
02256         AddVMEventFunction(VM_EVENT_DOS_EXIT_REBOOT_BEGIN,AddVMEventFunctionFuncPair(GUS_DOS_Exit));
02257     AddVMEventFunction(VM_EVENT_DOS_INIT_SHELL_READY,AddVMEventFunctionFuncPair(GUS_DOS_Boot));
02258 }
02259