Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

6581_.cpp

Go to the documentation of this file.
00001 //
00002 // /home/ms/sidplay/libsidplay/emu/RCS/6581_.cpp,v
00003 //
00004 // Contributions:
00005 //
00006 // Noise generation algorithm is used courtesy of Asger Alstrup Nielsen.
00007 // His original publication can be found on the SID home page.
00008 //
00009 // Noise table optimization proposed by Phillip Wooller. The output of
00010 // each table does not differ.
00011 //
00012 // MOS-8580 R5 combined waveforms recorded by Dennis "Deadman" Lindroos.
00013 // --------------------------------------------------------------------------
00014 //
00015 // --- MOS-6581 Emulator ---
00016 //
00017 // Copyright (c) 1994-1997 Michael Schwendt. All rights reserved.
00018 //
00019 // Redistribution and use  in source and  binary forms, either  unchanged or
00020 // modified, are permitted provided that the following conditions are met:
00021 //
00022 // (1)  Redistributions  of  source  code  must  retain  the above copyright
00023 // notice, this list of conditions and the following disclaimer.
00024 //
00025 // (2) Redistributions  in binary  form must  reproduce the  above copyright
00026 // notice,  this  list  of  conditions  and  the following disclaimer in the
00027 // documentation and/or other materials provided with the distribution.
00028 //
00029 // THIS SOFTWARE  IS PROVIDED  BY THE  AUTHOR ``AS  IS'' AND  ANY EXPRESS OR
00030 // IMPLIED  WARRANTIES,  INCLUDING,   BUT  NOT  LIMITED   TO,  THE   IMPLIED
00031 // WARRANTIES OF MERCHANTABILITY  AND FITNESS FOR  A PARTICULAR PURPOSE  ARE
00032 // DISCLAIMED.  IN NO EVENT SHALL  THE AUTHOR OR CONTRIBUTORS BE LIABLE  FOR
00033 // ANY DIRECT,  INDIRECT, INCIDENTAL,  SPECIAL, EXEMPLARY,  OR CONSEQUENTIAL
00034 // DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS
00035 // OR SERVICES;  LOSS OF  USE, DATA,  OR PROFITS;  OR BUSINESS INTERRUPTION)
00036 // HOWEVER  CAUSED  AND  ON  ANY  THEORY  OF LIABILITY, WHETHER IN CONTRACT,
00037 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  IN
00038 // ANY  WAY  OUT  OF  THE  USE  OF  THIS  SOFTWARE,  EVEN  IF ADVISED OF THE
00039 // POSSIBILITY OF SUCH DAMAGE.
00040 // --------------------------------------------------------------------------
00041 
00042 
00043 #if defined(SID_MONITOR) || defined(WB_DEBUG)
00044   #include <iostream.h>
00045   #include <iomanip.h>
00046 #endif
00047 
00048 #include "myendian.h"
00049 #include "sidtune.h"
00050 #include "6510_.h"
00051 #include "emucfg.h"
00052 #include "envelope.h"
00053 #include "samples.h"
00054 #include "wave6581.h"
00055 #include "wave8580.h"
00056 #include "6581_.h"
00057 #include "mixing.h"
00058 
00059 
00060 // constants
00061 static const uword apSpeed = 0x4000;
00062 static const udword noiseSeed = 0x7ffff8;
00063 
00064 #define lowPassParam filterTable
00065 
00066 
00067 // -------------------------------------------------------------------- Speed
00068 
00069 
00070 
00071 inline void sidEmu::calcValuesPerCall()
00072 {
00073         udword fastForwardFreq = PCMfreq;
00074         if ( fastForwardFactor != 128 )
00075         {
00076                 fastForwardFreq = (PCMfreq * fastForwardFactor) >> 7;  // divide by 128
00077         }
00078 #if defined(DIRECT_FIXPOINT)
00079         VALUES.l = ( VALUESorg.l = (((fastForwardFreq<<12)/calls)<<4) );
00080         VALUESadd.l = 0;
00081 #else
00082         VALUES = (VALUESorg = (fastForwardFreq / calls));
00083         VALUEScomma = ((fastForwardFreq % calls) * 65536UL) / calls;
00084         VALUESadd = 0;
00085 #endif
00086 }
00087 
00088 
00089 void sidEmu::sidEmuChangeReplayingSpeed()
00090 {
00091         calcValuesPerCall();
00092 }
00093 
00094 // PAL: Clock speed: 985248.4 Hz
00095 //      CIA 1 Timer A: $4025 (60 Hz)
00096 //
00097 // NTSC: Clock speed: 1022727.14 Hz
00098 //      CIA 1 Timer A: $4295 (60 Hz) 
00099 
00100 void sidEmu::sidEmuSetClockSpeed(int clockMode)
00101 {
00102         switch (clockMode)
00103         { 
00104          case SIDTUNE_CLOCK_NTSC:
00105                 {
00106                         C64_clockSpeed  = 1022727;
00107                         C64_fClockSpeed = 1022727.14f;
00108                         break;
00109                 }
00110          case SIDTUNE_CLOCK_PAL:
00111          default:
00112                 {
00113                         C64_clockSpeed  = 985248;
00114                         C64_fClockSpeed = (float)985248.4;
00115                         break;
00116                 }
00117         }
00118 }
00119 
00120 
00121 void sidEmu::sidEmuSetReplayingSpeed(int clockMode, uword callsPerSec)
00122 {
00123         switch (clockMode)
00124         { 
00125          case SIDTUNE_CLOCK_NTSC:
00126                 {
00127                         sidtuneClockSpeed = 1022727;
00128                         timer = (defaultTimer = 0x4295);
00129                         break;
00130                 }
00131          case SIDTUNE_CLOCK_PAL:
00132          default:
00133                 {
00134                         sidtuneClockSpeed = 985248;
00135                         timer = (defaultTimer = 0x4025);
00136                         break;
00137                 }
00138         }
00139         switch (callsPerSec)
00140         {
00141          case SIDTUNE_SPEED_CIA_1A:
00142                 {
00143                         timer = readLEword(c64mem2+0xdc04);
00144                         if (timer < 16)  // prevent overflow
00145                         {
00146                                 timer = defaultTimer;
00147                         }
00148                         calls = (uword)(sidtuneClockSpeed / timer);
00149                         break;
00150                 }
00151          default:
00152                 {
00153                         calls = callsPerSec;
00154                         break;
00155                 }
00156         }
00157         calcValuesPerCall();
00158 }
00159                                         
00160 
00161 void sidEmu::sidEmuUpdateReplayingSpeed()
00162 { 
00163         if ( timer != readLEword(c64mem2+0xdc04) )
00164         {
00165                 timer = readLEword(c64mem2+0xdc04);
00166                 // Prevent overflow
00167                 if ( timer < 16 )
00168                         timer = defaultTimer;
00169                 calls = (uword)(sidtuneClockSpeed / timer);
00170                 calcValuesPerCall();
00171         }
00172 }
00173 
00174 // --------------------------------------------------------------------------
00175 
00176 inline void waveAdvance(struct sidOperator* pVoice)
00177 {
00178 #if defined(DIRECT_FIXPOINT)
00179         pVoice->waveStep.l += pVoice->waveStepAdd.l;
00180         pVoice->waveStep.w[HI] &= 4095;
00181 #else
00182         pVoice->waveStepPnt += pVoice->waveStepAddPnt;
00183         pVoice->waveStep += ( pVoice->waveStepAdd + ( pVoice->waveStepPnt > 65535 ));
00184         pVoice->waveStepPnt &= 0xFFFF;
00185         pVoice->waveStep &= 4095;
00186 #endif
00187 }
00188 
00189 inline void sidEmu::noiseAdvance(struct sidOperator* pVoice)
00190 {
00191         pVoice->noiseStep += pVoice->noiseStepAdd;
00192         if (pVoice->noiseStep >= (1L<<20))
00193         {
00194                 pVoice->noiseStep -= (1L<<20);
00195 #if defined(DIRECT_FIXPOINT)
00196                 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) | 
00197                         (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
00198 #else
00199                 pVoice->noiseReg = (pVoice->noiseReg << 1) | 
00200                         (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
00201 #endif
00202 #if defined(DIRECT_FIXPOINT) && defined(LARGE_NOISE_TABLE)
00203                 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.w[LO]]
00204                                                            |noiseTableMSB[pVoice->noiseReg.w[HI]&0xff]);
00205 #elif defined(DIRECT_FIXPOINT)
00206                 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.b[LOLO]]
00207                                                            |noiseTableMID[pVoice->noiseReg.b[LOHI]]
00208                                                            |noiseTableMSB[pVoice->noiseReg.b[HILO]]);
00209 #else
00210                 pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg&0xff]
00211                                                            |noiseTableMID[pVoice->noiseReg>>8&0xff]
00212                                                            |noiseTableMSB[pVoice->noiseReg>>16&0xff]);
00213 #endif
00214         }
00215 }
00216 
00217 inline void sidEmu::noiseAdvanceHp(struct sidOperator* pVoice)
00218 {
00219         udword tmp = pVoice->noiseStepAdd;
00220         while (tmp >= (1L<<20))
00221         {
00222                 tmp -= (1L<<20);
00223 #if defined(DIRECT_FIXPOINT)
00224                 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) | 
00225                         (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
00226 #else
00227                 pVoice->noiseReg = (pVoice->noiseReg << 1) | 
00228                         (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
00229 #endif
00230         }
00231         pVoice->noiseStep += tmp;
00232         if (pVoice->noiseStep >= (1L<<20))
00233         {
00234                 pVoice->noiseStep -= (1L<<20);
00235 #if defined(DIRECT_FIXPOINT)
00236                 pVoice->noiseReg.l = (pVoice->noiseReg.l << 1) | 
00237                         (((pVoice->noiseReg.l >> 22) ^ (pVoice->noiseReg.l >> 17)) & 1);
00238 #else
00239                 pVoice->noiseReg = (pVoice->noiseReg << 1) | 
00240                         (((pVoice->noiseReg >> 22) ^ (pVoice->noiseReg >> 17)) & 1);
00241 #endif
00242         }
00243 #if defined(DIRECT_FIXPOINT) && defined(LARGE_NOISE_TABLE)
00244         pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.w[LO]]
00245                                                    |noiseTableMSB[pVoice->noiseReg.w[HI]&0xff]);
00246 #elif defined(DIRECT_FIXPOINT)
00247         pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg.b[LOLO]]
00248                                                    |noiseTableMID[pVoice->noiseReg.b[LOHI]]
00249                                                    |noiseTableMSB[pVoice->noiseReg.b[HILO]]);
00250 #else
00251         pVoice->noiseOutput = (noiseTableLSB[pVoice->noiseReg&0xff]
00252                                                    |noiseTableMID[pVoice->noiseReg>>8&0xff]
00253                                                    |noiseTableMSB[pVoice->noiseReg>>16&0xff]);
00254 #endif
00255 }
00256 
00257 
00258 #if defined(DIRECT_FIXPOINT)
00259   #define triangle triangleTable[pVoice->waveStep.w[HI]]
00260   #define sawtooth sawtoothTable[pVoice->waveStep.w[HI]]
00261   #define square squareTable[pVoice->waveStep.w[HI] + pVoice->pulseIndex]
00262   #define triSaw waveform30_8580[pVoice->waveStep.w[HI]]
00263 
00264 #ifdef LESS_CODE_BUT_ABIT_SLOWER // use index 0 -> content 0 if index >= 4096
00265   #define triSquare (waveform50[( ((pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) : 0 )]) 
00266   #define sawSquare (waveform60_8580[( ((pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) : 0 )]) 
00267   #define triSawSquare (waveform70_8580[( ((pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth) : 0 )]) 
00268 #else
00269   #define triSquare waveform50[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
00270   #define sawSquare waveform60_8580[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
00271   #define triSawSquare waveform70_8580[pVoice->waveStep.w[HI] + pVoice->SIDpulseWidth]
00272 #endif
00273 
00274 #else
00275   #define triangle triangleTable[pVoice->waveStep]
00276   #define sawtooth sawtoothTable[pVoice->waveStep]
00277   #define square squareTable[pVoice->waveStep + pVoice->pulseIndex]
00278   #define triSaw waveform30_8580[pVoice->waveStep]
00279 #ifdef LESS_CODE_BUT_ABIT_SLOWER
00280   #define triSquare (waveform50[ ((pVoice->waveStep + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep + pVoice->SIDpulseWidth) : 0 ] )
00281   #define sawSquare (waveform60_8580[ ((pVoice->waveStep + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep + pVoice->SIDpulseWidth) : 0 ] )
00282   #define triSawSquare (waveform70_8580[ ((pVoice->waveStep + pVoice->SIDpulseWidth) < 4096) ? (pVoice->waveStep + pVoice->SIDpulseWidth) : 0 ] )
00283 #else
00284   #define sawSquare waveform60_8580[pVoice->waveStep + pVoice->SIDpulseWidth]
00285   #define triSawSquare waveform70_8580[pVoice->waveStep + pVoice->SIDpulseWidth]
00286 #endif
00287 
00288 #endif
00289 
00290 
00291 void sidEmu::sidMode00(struct sidOperator* pVoice)  {
00292         pVoice->output = (pVoice->filtIO-0x80);
00293         waveAdvance(pVoice);
00294 }
00295 
00296 /* TODO 
00297 static void sidModeReal00(struct sidOperator* pVoice)  {
00298         pVoice->output = 0;
00299         waveAdvance(pVoice);
00300 }
00301 */
00302 
00303 void sidEmu::sidMode10(struct sidOperator* pVoice)  {
00304   pVoice->output = triangle;
00305   waveAdvance(pVoice);
00306 }
00307 
00308 void sidEmu::sidMode20(struct sidOperator* pVoice)  {
00309   pVoice->output = sawtooth;
00310   waveAdvance(pVoice);
00311 }
00312 
00313 void sidEmu::sidMode30(struct sidOperator* pVoice)  {
00314 #ifdef SIDEMU_OLD_WAVE30
00315   pVoice->output = ( triangle & sawtooth );
00316 #else
00317   pVoice->output = triSaw;
00318 #endif
00319   waveAdvance(pVoice);
00320 }
00321 
00322 void sidEmu::sidMode40(struct sidOperator* pVoice)  {
00323   pVoice->output = square;
00324   waveAdvance(pVoice);
00325 }
00326 
00327 void sidEmu::sidMode50(struct sidOperator* pVoice)  {
00328   pVoice->output = triSquare;
00329   waveAdvance(pVoice);
00330 }
00331 
00332 void sidEmu::sidMode60(struct sidOperator* pVoice)  {
00333   pVoice->output = sawSquare;
00334   waveAdvance(pVoice);
00335 }
00336 
00337 void sidEmu::sidMode70(struct sidOperator* pVoice)  {
00338   pVoice->output = triSawSquare;
00339   waveAdvance(pVoice);
00340 }
00341 
00342 void sidEmu::sidMode80(struct sidOperator* pVoice)  {
00343   pVoice->output = pVoice->noiseOutput;
00344   waveAdvance(pVoice);
00345   noiseAdvance(pVoice);
00346 }
00347 
00348 void sidEmu::sidMode80hp(struct sidOperator* pVoice)  {
00349   pVoice->output = pVoice->noiseOutput;
00350   waveAdvance(pVoice);
00351   noiseAdvanceHp(pVoice);
00352 }
00353 
00354 void sidEmu::sidModeLock(struct sidOperator* pVoice)
00355 {
00356         pVoice->noiseIsLocked = true;
00357         pVoice->output = (pVoice->filtIO-0x80);
00358         waveAdvance(pVoice);
00359 }
00360 
00361 //
00362 // 
00363 //
00364 
00365 void sidEmu::sidMode14(struct sidOperator* pVoice)
00366 {
00367 #if defined(DIRECT_FIXPOINT)
00368   if ( pVoice->modulator->waveStep.w[HI] < 2048 )
00369 #else
00370   if ( pVoice->modulator->waveStep < 2048 )
00371 #endif
00372         pVoice->output = triangle;
00373   else
00374         pVoice->output = 0xFF ^ triangle;
00375   waveAdvance(pVoice);
00376 }
00377 
00378 void sidEmu::sidMode34(struct sidOperator* pVoice)  {
00379 #if defined(DIRECT_FIXPOINT)
00380   if ( pVoice->modulator->waveStep.w[HI] < 2048 )
00381 #else
00382   if ( pVoice->modulator->waveStep < 2048 )
00383 #endif
00384 #ifdef SIDEMU_OLD_WAVE30
00385         pVoice->output = triangle & sawtooth;
00386   else
00387         pVoice->output = (0xFF^triangle) & (0xFF^sawtooth);
00388 #else
00389         pVoice->output = triSaw;
00390   else
00391         pVoice->output = 0xFF ^ triSaw;
00392 #endif
00393   waveAdvance(pVoice);
00394 }
00395 
00396 void sidEmu::sidMode54(struct sidOperator* pVoice)  {
00397 #if defined(DIRECT_FIXPOINT)
00398   if ( pVoice->modulator->waveStep.w[HI] < 2048 )
00399 #else
00400   if ( pVoice->modulator->waveStep < 2048 )
00401 #endif
00402         pVoice->output = triSquare;
00403   else
00404     pVoice->output = 0xFF ^ triSquare;
00405   waveAdvance(pVoice);
00406 }
00407 
00408 void sidEmu::sidMode74(struct sidOperator* pVoice)  {
00409 #if defined(DIRECT_FIXPOINT)
00410   if ( pVoice->modulator->waveStep.w[HI] < 2048 )
00411 #else
00412   if ( pVoice->modulator->waveStep < 2048 )
00413 #endif
00414         pVoice->output = triSawSquare;
00415   else
00416     pVoice->output = 0xFF ^ triSawSquare;
00417   waveAdvance(pVoice);
00418 }
00419 
00420 //
00421 // 
00422 //
00423 
00424 inline void waveCalcCycleLen(struct sidOperator* pVoice)
00425 {
00426 #if defined(DIRECT_FIXPOINT)
00427         pVoice->cycleAddLen.w[HI] = 0;
00428         pVoice->cycleAddLen.l += pVoice->cycleLen.l;
00429         pVoice->cycleLenCount = pVoice->cycleAddLen.w[HI];
00430 #else           
00431         pVoice->cycleAddLenPnt += pVoice->cycleLenPnt;
00432         pVoice->cycleLenCount = pVoice->cycleLen + ( pVoice->cycleAddLenPnt > 65535 );
00433         pVoice->cycleAddLenPnt &= 0xFFFF;
00434 #endif
00435         // If we keep the value cycleLen between 1 <= x <= 65535, 
00436         // the following check is not required.
00437 //      if ( pVoice->cycleLenCount == 0 )
00438 //      {
00439 //#if defined(DIRECT_FIXPOINT)
00440 //              pVoice->waveStep.l = 0;
00441 //#else
00442 //              pVoice->waveStep = (pVoice->waveStepPnt = 0);
00443 //#endif
00444 //              pVoice->cycleLenCount = 0;
00445 //      }
00446 //      else
00447 //      {
00448 #if defined(DIRECT_FIXPOINT)
00449                 register uword diff = pVoice->cycleLenCount - pVoice->cycleLen.w[HI];
00450 #else
00451                 register uword diff = pVoice->cycleLenCount - pVoice->cycleLen;
00452 #endif
00453                 if ( pVoice->wavePre[diff].len != pVoice->cycleLenCount )
00454                 {
00455                         pVoice->wavePre[diff].len = (uword)(pVoice->cycleLenCount);
00456 #if defined(DIRECT_FIXPOINT)
00457                         pVoice->wavePre[diff].stp = (pVoice->waveStepAdd.l = (4096UL*65536UL) / pVoice->cycleLenCount);
00458 #else
00459                         pVoice->wavePre[diff].stp = (uword)(pVoice->waveStepAdd = 4096UL / pVoice->cycleLenCount);
00460                         pVoice->wavePre[diff].pnt = (pVoice->waveStepAddPnt = ((4096UL % pVoice->cycleLenCount) * 65536UL) / pVoice->cycleLenCount);
00461 #endif
00462                 }
00463                 else
00464                 {
00465 #if defined(DIRECT_FIXPOINT)
00466                         pVoice->waveStepAdd.l = pVoice->wavePre[diff].stp;
00467 #else
00468                         pVoice->waveStepAdd = pVoice->wavePre[diff].stp;
00469                         pVoice->waveStepAddPnt = pVoice->wavePre[diff].pnt;
00470 #endif
00471                 }
00472 //      }  // see above (opening bracket)
00473 }
00474 
00475 inline void sidEmu::waveCalcFilter(struct sidOperator* pVoice)
00476 {
00477         if ( pVoice->filtEnabled )
00478         {
00479                 if ( filterType != 0 )
00480                 {
00481                         if ( filterType == 0x20 )
00482                         {
00483                                 pVoice->filtLow += ( pVoice->filtRef * filterDy );
00484                                 float tmp = (float)pVoice->filtIO - pVoice->filtLow;
00485                                 tmp -= pVoice->filtRef * filterResDy;
00486                                 pVoice->filtRef += ( tmp * (filterDy) );
00487                                 pVoice->filtIO = (sbyte)(pVoice->filtRef-pVoice->filtLow/4);
00488                         }
00489                         else if (filterType == 0x40)
00490                         {
00491                                 pVoice->filtLow += (float)( pVoice->filtRef * filterDy * 0.1 );
00492                                 float tmp = (float)pVoice->filtIO - pVoice->filtLow;
00493                                 tmp -= pVoice->filtRef * filterResDy;
00494                                 pVoice->filtRef += ( tmp * (filterDy) );
00495                                 float tmp2 = pVoice->filtRef - pVoice->filtIO/8;
00496                                 if (tmp2 < -128)
00497                                         tmp2 = -128;
00498                                 if (tmp2 > 127)
00499                                         tmp2 = 127;
00500                                 pVoice->filtIO = (sbyte)tmp2;
00501                         }
00502                         else
00503                         {
00504                                 pVoice->filtLow += ( pVoice->filtRef * filterDy );
00505                                 float sample = pVoice->filtIO;
00506                                 float sample2 = sample - pVoice->filtLow;
00507                                 int tmp = (int)sample2;
00508                                 sample2 -= pVoice->filtRef * filterResDy;
00509                                 pVoice->filtRef += ( sample2 * filterDy );
00510                         
00511                                 if ( filterType == 0x10 )
00512                                 {
00513                                         pVoice->filtIO = (sbyte)pVoice->filtLow;
00514                                 }
00515                                 else if ( filterType == 0x30 )
00516                                 {
00517                                         pVoice->filtIO = (sbyte)pVoice->filtLow;
00518                                 }
00519                                 else if ( filterType == 0x50 )
00520                                 {
00521                                         pVoice->filtIO = (sbyte)(sample - (tmp >> 1));
00522                                 }
00523                                 else if ( filterType == 0x60 )
00524                                 {
00525                                         pVoice->filtIO = (sbyte)tmp;
00526                                 }
00527                                 else if ( filterType == 0x70 )
00528                                 {
00529                                         pVoice->filtIO = (sbyte)(sample - (tmp >> 1));
00530                                 }
00531                         }
00532                 }
00533                 else // filterType == 0x00
00534                 {
00535                         pVoice->filtIO = 0;
00536                 }
00537         }
00538 }
00539 
00540 
00541 sbyte sidEmu::waveCalcMute(struct sidOperator* pVoice)
00542         {
00543 //      iTheEnvelope->callADSRproc(pVoice);
00544         
00545         (iTheEnvelope->*pVoice->ADSRproc)(pVoice);  // just process envelope
00546         return pVoice->filtIO;
00547         }
00548 
00549 
00550 sbyte sidEmu::waveCalcNormal(struct sidOperator* pVoice)
00551         {
00552  
00553         if ( pVoice->cycleLenCount <= 0 )
00554         {
00555                 waveCalcCycleLen(pVoice);
00556                 if (( pVoice->SIDctrl & 0x40 ) == 0x40 )
00557                 {
00558                         pVoice->pulseIndex = pVoice->newPulseIndex;
00559                         if ( pVoice->pulseIndex > 2048 )
00560                         {
00561 #if defined(DIRECT_FIXPOINT)
00562                                 pVoice->waveStep.w[HI] = 0;
00563 #else
00564                                 pVoice->waveStep = 0;
00565 #endif
00566                         }
00567                 }
00568         }
00569 
00570         (this->*pVoice->waveProc)(pVoice);
00571 //      (*pVoice->waveProc)(pVoice); - original
00572 
00573 //      int index = iTheEnvelope->callADSRproc(pVoice);
00574         int index = (iTheEnvelope->*pVoice->ADSRproc)(pVoice);
00575 
00576         pVoice->filtIO = iTheEmuEngine->ampMod1x8[index | pVoice->output];
00577 //      pVoice->filtIO = iTheEmuEngine->ampMod1x8[(*pVoice->ADSRproc)(pVoice)|pVoice->output];
00578         ((sidEmu*)this)->waveCalcFilter(pVoice); //TODO: check this
00579 
00580         return pVoice->filtIO;
00581 }
00582 
00583 sbyte sidEmu::waveCalcRangeCheck(struct sidOperator* pVoice)
00584         {
00585 
00586 #if defined(DIRECT_FIXPOINT)
00587         pVoice->waveStepOld = pVoice->waveStep.w[HI];
00588         (this->*pVoice->waveProc)(pVoice);
00589         if (pVoice->waveStep.w[HI] < pVoice->waveStepOld)
00590 #else
00591         pVoice->waveStepOld = pVoice->waveStep;
00592         (this->*pVoice->waveProc)(pVoice);
00593         if (pVoice->waveStep < pVoice->waveStepOld)
00594 #endif
00595         {
00596                 // Next step switch back to normal calculation.
00597                 pVoice->cycleLenCount = 0;
00598                 pVoice->outProc = &sidEmu::waveCalcNormal;
00599 #if defined(DIRECT_FIXPOINT)
00600                                 pVoice->waveStep.w[HI] = 4095;
00601 #else
00602                                 pVoice->waveStep = 4095;
00603 #endif
00604         }
00605 
00606         int index = (iTheEnvelope->*pVoice->ADSRproc)(pVoice);
00607         pVoice->filtIO = iTheEmuEngine->ampMod1x8[index | pVoice->output];
00608 
00609 //      pVoice->filtIO = iTheEmuEngine->ampMod1x8[iTheEnvelope->callADSRproc(pVoice)|pVoice->output];
00610 //      pVoice->filtIO = iTheEmuEngine->ampMod1x8[(*pVoice->ADSRproc)(pVoice)|pVoice->output];
00611         ((sidEmu*)this)->waveCalcFilter(pVoice); //TODO: check this
00612         return pVoice->filtIO;
00613 }
00614 
00615 // -------------------------------------------------- Operator frame set-up 1
00616 
00617 inline void sidEmu::sidEmuSet(struct sidOperator* pVoice, uword sidIndex)
00618 {
00619         pVoice->SIDfreq = readLEword(c64mem2+sidIndex);
00620 
00621         pVoice->SIDpulseWidth = (readLEword(c64mem2+sidIndex+2) & 0x0FFF);
00622         pVoice->newPulseIndex = 4096 - pVoice->SIDpulseWidth;
00623 #if defined(DIRECT_FIXPOINT)
00624         if ( ((pVoice->waveStep.w[HI] + pVoice->pulseIndex) >= 0x1000)
00625                 && ((pVoice->waveStep.w[HI] + pVoice->newPulseIndex) >= 0x1000) )
00626         {
00627                 pVoice->pulseIndex = pVoice->newPulseIndex;
00628         }
00629         else if ( ((pVoice->waveStep.w[HI] + pVoice->pulseIndex) < 0x1000)
00630                 && ((pVoice->waveStep.w[HI] + pVoice->newPulseIndex) < 0x1000) )
00631         {
00632                 pVoice->pulseIndex = pVoice->newPulseIndex;
00633         }
00634 #else
00635         if ( ((pVoice->waveStep + pVoice->pulseIndex) >= 0x1000)
00636                 && ((pVoice->waveStep + pVoice->newPulseIndex) >= 0x1000) )
00637         {
00638                 pVoice->pulseIndex = pVoice->newPulseIndex;
00639         }
00640         else if ( ((pVoice->waveStep + pVoice->pulseIndex) < 0x1000)
00641                 && ((pVoice->waveStep + pVoice->newPulseIndex) < 0x1000) )
00642         {
00643                 pVoice->pulseIndex = pVoice->newPulseIndex;
00644         }
00645 #endif
00646 
00647     ubyte enveTemp, newWave, oldWave;
00648         
00649         oldWave = pVoice->SIDctrl;
00650         enveTemp = pVoice->ADSRctrl;
00651         pVoice->SIDctrl = (newWave = c64mem2[sidIndex +4]);
00652 
00653         if (( newWave & 1 ) ==0 )
00654         {
00655                 if (( oldWave & 1 ) !=0 )
00656                         enveTemp = ENVE_STARTRELEASE;
00657 //              else if ( pVoice->gateOnCtrl )
00658 //              {
00659 //                      enveTemp = ENVE_STARTSHORTATTACK;
00660 //              }
00661         }
00662         else if ( pVoice->gateOffCtrl || ((oldWave&1)==0) )
00663         {
00664                 enveTemp = ENVE_STARTATTACK;
00665                 if (doAutoPanning && updateAutoPanning)
00666                 {
00667                         // Swap source/destination position.
00668                         uword tmp = pVoice->gainSource;
00669                         pVoice->gainSource = pVoice->gainDest;
00670                         pVoice->gainDest = tmp;
00671                         if ((pVoice->gainDest^pVoice->gainSource) == 0)
00672                         {
00673                                 // Mute voice.
00674                                 pVoice->gainLeft = (pVoice->gainRight = 0x0000+0x80);
00675                         }
00676                         else
00677                         {
00678                                 // Start from middle position.
00679                                 pVoice->gainLeft = pVoice->gainLeftCentered;
00680                                 pVoice->gainRight = pVoice->gainRightCentered;
00681                         }
00682                         // Determine direction.
00683                         // true  = L > R : L down, R up
00684                         // false = L < R : L up, R down
00685                         pVoice->gainDirec = (pVoice->gainLeft > pVoice->gainDest);
00686                 }
00687         }
00688 
00689         if (doAutoPanning && updateAutoPanning && (enveTemp!=ENVE_STARTATTACK))
00690         {
00691                 if (pVoice->gainDirec)
00692                 {
00693                         if (pVoice->gainLeft > pVoice->gainDest)
00694                         {
00695                                 pVoice->gainLeft -= 0x0100;
00696                                 pVoice->gainRight += 0x0100;
00697                         }
00698                         else
00699                         {
00700                                 // Swap source/destination position.
00701                                 uword tmp = pVoice->gainSource;
00702                                 pVoice->gainSource = pVoice->gainDest;
00703                                 pVoice->gainDest = tmp;
00704                                 // Inverse direction.
00705                                 pVoice->gainDirec = false;
00706                         }
00707                 }
00708                 else
00709                 {
00710                         if (pVoice->gainRight > pVoice->gainSource)
00711                         {
00712                                 pVoice->gainLeft += 0x0100;
00713                                 pVoice->gainRight -= 0x0100;
00714                         }
00715                         else
00716                         {
00717                                 pVoice->gainDirec = true;
00718                                 // Swap source/destination position.
00719                                 uword tmp = pVoice->gainSource;
00720                                 pVoice->gainSource = pVoice->gainDest;
00721                                 // Inverse direction.
00722                                 pVoice->gainDest = tmp;
00723                         }
00724                 }
00725         }
00726 
00727         if ((( oldWave ^ newWave ) & 0xF0 ) != 0 )
00728         {
00729                 pVoice->cycleLenCount = 0;
00730         }
00731         
00732         ubyte ADtemp = c64mem2[sidIndex +5];
00733         ubyte SRtemp = c64mem2[sidIndex +6];
00734         if ( pVoice->SIDAD != ADtemp )
00735         {
00736                 enveTemp |= ENVE_ALTER;
00737         }
00738         else if ( pVoice->SIDSR != SRtemp )
00739         {
00740                 enveTemp |= ENVE_ALTER;
00741         }
00742         pVoice->SIDAD = ADtemp;
00743         pVoice->SIDSR = SRtemp;
00744         extern const ubyte masterVolumeLevels[16];  // -> envelope.cpp
00745         ubyte tmpSusVol = masterVolumeLevels[SRtemp >> 4];
00746         if (pVoice->ADSRctrl != ENVE_SUSTAIN)  // !!!
00747         {
00748                 pVoice->enveSusVol = tmpSusVol;
00749         }
00750         else
00751         {
00752                 if ( pVoice->enveSusVol > pVoice->enveVol )
00753                         pVoice->enveSusVol = 0;
00754                 else
00755                         pVoice->enveSusVol = tmpSusVol;
00756         }
00757         
00758         pVoice->ADSRproc = (iTheEnvelope->getEnveModeTable())[enveTemp>>1];  // shifting out the KEY-bit
00759         pVoice->ADSRctrl = enveTemp & (255-ENVE_ALTER-1);
00760   
00761         if ( filterEnabled )
00762         {
00763                 if (( c64mem2[0xd417] & pVoice->filtVoiceMask ) != 0 )
00764                 {
00765                         pVoice->filtEnabled = true;
00766                 }
00767                 else
00768                 {
00769                         pVoice->filtEnabled = false;
00770                 }
00771         }
00772         else
00773         {
00774                 pVoice->filtEnabled = false;
00775         }
00776 }
00777 
00778 // -------------------------------------------------- Operator frame set-up 2
00779 #if 0 //TODO
00780 // MOS-8580, MOS-6581 (no 70)
00781 ptr2sidVoidFunc sidEmu::sidModeNormalTable[16] =
00782 {
00783   sidEmu::sidMode00, sidEmu::sidMode10, sidEmu::sidMode20, sidEmu::sidMode30, sidEmu::sidMode40, sidEmu::sidMode50, sidEmu::sidMode60, sidEmu::sidMode70,
00784   sidEmu::sidMode80, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock
00785 };
00786 
00787 // MOS-8580, MOS-6581 (no 74)
00788 ptr2sidVoidFunc sidEmu::sidModeRingTable[16] =
00789 {
00790   sidEmu::sidMode00, sidEmu::sidMode14, sidEmu::sidMode00, sidEmu::sidMode34, sidEmu::sidMode00, sidEmu::sidMode54, sidEmu::sidMode00, sidEmu::sidMode74,
00791   sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock, sidEmu::sidModeLock
00792 };
00793 #endif
00794 
00795 inline void sidEmu::sidEmuSet2(struct sidOperator* pVoice)
00796 {
00797         pVoice->outProc = &sidEmu::waveCalcNormal;
00798         pVoice->sync = false;
00799 
00800         if ( (pVoice->SIDfreq < 16)
00801                 || ((pVoice->SIDctrl & 8) != 0) )
00802         {
00803                 pVoice->outProc = &sidEmu::waveCalcMute;
00804                 if (pVoice->SIDfreq == 0)
00805                 {
00806 #if defined(DIRECT_FIXPOINT)
00807                         pVoice->cycleLen.l = (pVoice->cycleAddLen.l = 0);
00808                         pVoice->waveStep.l = 0;
00809 #else
00810                         pVoice->cycleLen = (pVoice->cycleLenPnt = 0);
00811                         pVoice->cycleAddLenPnt = 0;
00812                         pVoice->waveStep = 0;
00813                         pVoice->waveStepPnt = 0;
00814 #endif
00815                         pVoice->curSIDfreq = (pVoice->curNoiseFreq = 0);
00816                         pVoice->noiseStepAdd = 0;
00817                         pVoice->cycleLenCount = 0;
00818                 }
00819                 if ((pVoice->SIDctrl & 8) != 0)
00820                 {
00821                         if (pVoice->noiseIsLocked)
00822                         {
00823                                 pVoice->noiseIsLocked = false;
00824 #if defined(DIRECT_FIXPOINT)
00825                                 pVoice->noiseReg.l = noiseSeed;
00826 #else
00827                                 pVoice->noiseReg = noiseSeed;
00828 #endif
00829                         }
00830                 }
00831         }
00832         else
00833         {
00834                 if ( pVoice->curSIDfreq != pVoice->SIDfreq )
00835                 {
00836                         pVoice->curSIDfreq = (uword)(pVoice->SIDfreq);
00837                         // We keep the value cycleLen between 1 <= x <= 65535.
00838                         // This makes a range-check in waveCalcCycleLen() unrequired.
00839 #if defined(DIRECT_FIXPOINT)
00840                         pVoice->cycleLen.l = ((PCMsid << 12) / pVoice->SIDfreq) << 4;
00841                         if (pVoice->cycleLenCount > 0)
00842                         {
00843                                 waveCalcCycleLen(pVoice);
00844                                 pVoice->outProc = &sidEmu::waveCalcRangeCheck;
00845                         }
00846 #else
00847                         pVoice->cycleLen = (uword)(PCMsid / pVoice->SIDfreq);
00848                         pVoice->cycleLenPnt = (uword)((( PCMsid % pVoice->SIDfreq ) * 65536UL ) / pVoice->SIDfreq);
00849                         if (pVoice->cycleLenCount > 0)
00850                         {
00851                                 waveCalcCycleLen(pVoice);
00852                                 pVoice->outProc = &sidEmu::waveCalcRangeCheck;
00853                         }
00854 #endif
00855                 }
00856   
00857                 if ((( pVoice->SIDctrl & 0x80 ) == 0x80 ) && ( pVoice->curNoiseFreq != pVoice->SIDfreq ))
00858                 {
00859                         pVoice->curNoiseFreq = (uword)(pVoice->SIDfreq);
00860                         pVoice->noiseStepAdd = (PCMsidNoise * pVoice->SIDfreq) >> 8;
00861                         if (pVoice->noiseStepAdd >= (1L<<21))
00862                                 sidModeNormalTable[8] = &sidEmu::sidMode80hp;
00863                         else
00864                                 sidModeNormalTable[8] = &sidEmu::sidMode80;
00865                 }
00866         
00867                 if (( pVoice->SIDctrl & 2 ) != 0 )
00868                 {
00869                         if ( ( pVoice->modulator->SIDfreq == 0 ) || (( pVoice->modulator->SIDctrl & 8 ) != 0 ) )
00870                         {
00871                                 ;
00872                         }
00873                         else if ( (( pVoice->carrier->SIDctrl & 2 ) != 0 ) &&
00874                                          ( pVoice->modulator->SIDfreq >= ( pVoice->SIDfreq << 1 )) )
00875                         {
00876                                 ;
00877                         }
00878                         else
00879                         {
00880                                 pVoice->sync = true;
00881                         }
00882                 }
00883                 
00884                 if ((( pVoice->SIDctrl & 0x14 ) == 0x14 ) && ( pVoice->modulator->SIDfreq != 0 ))
00885                         pVoice->waveProc = sidModeRingTable[pVoice->SIDctrl >> 4];
00886                 else
00887                         pVoice->waveProc = sidModeNormalTable[pVoice->SIDctrl >> 4];
00888         }
00889 }
00890 
00891 
00892 
00893 void sidEmu::sidEmuFillBuffer( emuEngine& thisEmu,
00894                                            sidTune& thistune, 
00895                                            void* buffer, udword bufferLen )
00896         {
00897 
00898         
00899 
00900         // Ensure a sane status of the whole emulator.
00901         if ( thisEmu.isReady && thistune.returnStatus() )
00902                 {
00903                 // split sample buffer into pieces for # voices
00904                 if ( thisEmu.config.volumeControl == SIDEMU_HWMIXING )
00905                         {
00906                         bufferLen >>= 2; // or /4
00907                         splitBufferLen = bufferLen;
00908                         }
00909                 // both, 16-bit and stereo samples take more memory
00910                 // hence fewer samples fit into the buffer
00911                 bufferLen >>= thisEmu.bufferScale;
00912                 
00913 #if defined(SIDEMU_TIME_COUNT)
00914                 if (prevBufferLen != bufferLen)
00915                         {
00916                         prevBufferLen = bufferLen;
00917                         scaledBufferLen = (bufferLen<<7) / fastForwardFactor;
00918                         }
00919                 thisEmu.bytesCount += scaledBufferLen;
00920                 while (thisEmu.bytesCount >= thisEmu.config.frequency)
00921                         {
00922                         thisEmu.bytesCount -= thisEmu.config.frequency;
00923                         thisEmu.secondsThisSong++;
00924                         thisEmu.secondsTotal++;
00925                         }
00926 #endif
00927                 
00928                 while ( bufferLen > 0 )
00929                         {
00930                         if ( toFill > bufferLen )
00931                                 {
00932                                 buffer = thisEmu.iTheMixer->fillFunc(buffer, bufferLen); //AEH
00933                                 toFill -= (uword)bufferLen;
00934                                 bufferLen = 0;
00935                                 }
00936                         else if ( toFill > 0 )
00937                                 {
00938                                 buffer = thisEmu.iTheMixer->fillFunc(buffer, toFill); //AEH - HERE IS THE BUG!!!
00939                                 bufferLen -= toFill;
00940                                 toFill = 0;
00941                                 }
00942                         
00943                         if ( toFill == 0 )
00944                                 {
00945                                 iThe6510->optr3readWave = optr3.output;
00946                                 iThe6510->optr3readEnve = optr3.enveVol;
00947                                 
00948                                 uword replayPC = thistune.returnPlayAddr();
00949                                 // playRamRom was set by external player interface.
00950                                 if ( replayPC == 0 )
00951                                         {
00952                                         thisEmu.playRamRom = c64mem1[1];
00953                                         if ((thisEmu.playRamRom & 2) != 0)  // isKernal ?
00954                                                 replayPC = readLEword(c64mem1+0x0314);  // IRQ
00955                                         else
00956                                                 replayPC = readLEword(c64mem1+0xfffe);  // NMI
00957                                         }
00958                                 //bool retcode = 
00959                                 iThe6510->interpreter(replayPC, thisEmu.playRamRom, 0, 0, 0);
00960                                 
00961                                 if (thistune.returnSongSpeed() == 0)
00962                                         {
00963                                         sidEmuUpdateReplayingSpeed();
00964                                         }
00965                                 
00966                                 iTheEnvelope->masterVolume = ( c64mem2[0xd418] & 15 );
00967                                 iTheEnvelope->masterVolumeAmplIndex = iTheEnvelope->masterVolume << 8;
00968 
00969                                 optr1.gateOnCtrl = iThe6510->sidKeysOn[4];
00970                                 optr1.gateOffCtrl = iThe6510->sidKeysOff[4];
00971                                 sidEmuSet( &optr1, 0xd400 );
00972                                 optr2.gateOnCtrl = iThe6510->sidKeysOn[4+7];
00973                                 optr2.gateOffCtrl = iThe6510->sidKeysOff[4+7];
00974                                 sidEmuSet( &optr2, 0xd407 );
00975                                 optr3.gateOnCtrl = iThe6510->sidKeysOn[4+14];
00976                                 optr3.gateOffCtrl = iThe6510->sidKeysOff[4+14];
00977                                 sidEmuSet( &optr3, 0xd40e );
00978                                 
00979                                 filterType = c64mem2[0xd418] & 0x70;
00980                                 if (filterType != filterCurType)
00981                                         {
00982                                         filterCurType = filterType;
00983                                         optr1.filtLow = (optr1.filtRef = 0);
00984                                         optr2.filtLow = (optr2.filtRef = 0);
00985                                         optr3.filtLow = (optr3.filtRef = 0);
00986                                         }
00987                                 if ( filterEnabled )
00988                                         {
00989 
00990                                         filterValue = 0x7ff & ( (c64mem2[0xd415]&7) | ( (uword)c64mem2[0xd416] << 3 ));
00991                                         if (filterType == 0x20)
00992                                                 filterDy = bandPassParam[filterValue];
00993                                         else
00994                                                 filterDy = lowPassParam[filterValue];
00995                                         filterResDy = filterResTable[c64mem2[0xd417] >> 4] - filterDy;
00996                                         if ( filterResDy < 1.0 )
00997                                                 filterResDy = 1.0;
00998                                         }
00999                                 
01000                                 sidEmuSet2( &optr1 );
01001                                 sidEmuSet2( &optr2 );  // somewhere here...
01002                                 sidEmuSet2( &optr3 );
01003                                 
01004                                 iTheSampler->sampleEmuCheckForInit();
01005                                 
01006 #if defined(DIRECT_FIXPOINT)
01007                                 VALUESadd.w[HI] = 0;
01008                                 VALUESadd.l += VALUES.l;
01009                                 toFill = VALUESadd.w[HI];
01010 #else
01011                                 udword temp = (VALUESadd + VALUEScomma);
01012                                 VALUESadd = temp & 0xFFFF;
01013                                 toFill = VALUES + (temp > 65535);
01014 #endif
01015                                 
01016                                 // Decide whether to update/start auto-panning.
01017                                 if ((apCount += timer) >= apSpeed)
01018                                         {
01019                                         apCount -= apSpeed;
01020                                         updateAutoPanning = true;
01021                                         }
01022                                 else
01023                                         updateAutoPanning = false;
01024                                 
01025                                 }
01026                         } // end while bufferLen
01027                 } // end if status
01028         }
01029 
01030 
01031 bool sidEmu::sidEmuFastForwardReplay( int percent )
01032 {
01033         if (( percent < 1 ) || ( percent > 100 ))
01034         {
01035                 return false;
01036         }
01037         else
01038         {
01039                 fastForwardFactor = (percent<<7)/100;  // we use 2^7 as divider
01040 #if defined(SIDEMU_TIME_COUNT)
01041                 scaledBufferLen = (prevBufferLen<<7)/fastForwardFactor;
01042 #endif
01043                 calcValuesPerCall();
01044                 // Ensure that we calculate at least a single sample per player call.
01045                 // Still possible would be also (0 < x < 1.0).
01046                 // Else (x = 0) this would cause a deadlock in the buffer fill loop.
01047 #if defined(DIRECT_FIXPOINT)
01048                 if (VALUES.w[HI] < 1)
01049                 {
01050                         VALUES.l = (VALUESorg.l = 0);
01051                         VALUES.w[HI] = (VALUESorg.w[HI] = 1);
01052                 }
01053 #else
01054                 if (VALUES < 1)
01055                 {
01056                         VALUES = (VALUESorg = 1);
01057                         VALUEScomma = 0;
01058                 }
01059 #endif
01060                 return true;
01061         }
01062 }
01063 
01064 // --------------------------------------------------------------------- Init
01065 
01066 void sidEmu::initWaveformTables(bool isNewSID)
01067 {
01068         int i,j;
01069         uword k;
01070         
01071         k = 0;
01072         for ( i = 0; i < 256; i++ )
01073                 for ( j = 0; j < 8; j++ )
01074                         triangleTable[k++] = (ubyte)i;
01075         for ( i = 255; i >= 0; i-- )
01076                 for ( j = 0; j < 8; j++ )
01077                         triangleTable[k++] = (ubyte)i;
01078 
01080 //      in    | out
01081 // 0x0000 | 0x00
01082 // 0x0001 | 0x00
01083 // 0x0008 | 0x01
01084 // 0x0fff | 0xff
01085 // 0x1000 | 0xff
01086 // 0x1fff | 0x00
01087 
01088 
01089 
01090         k = 0;
01091         for ( i = 0; i < 256; i++ )
01092                 for ( j = 0; j < 16; j++ )
01093                         sawtoothTable[k++] = (ubyte)i;
01094 
01095 // 00000000000000001111111111111111222222222
01096 //
01097 //  out = sawtooth[in]
01098 //
01099 //  in    | out
01100 //  0x00  | 0x00
01101 //  0x01  | 0x00
01102 //  0x10  | 0x01
01103 //  0xfff | 0xff
01104 //  
01105 // -> out = in >> 4; TODO for SawTooth table
01106         
01107         k = 0;
01108         for ( i = 0; i < 4096; i++ )  
01109                 squareTable[k++] = 0;
01110         for ( i = 0; i < 4096; i++ )  
01111                 squareTable[k++] = 255;
01112 
01113 // in     | out
01114 // 0x0000 | 0x00
01115 // 0x0fff | 0x00
01116 // 0x1000 | 0xff
01117 // 0x1fff | 0xff
01118 //
01119 // -> out = in & 0x1000 ? 255 : 0;
01120 
01121 
01122 #ifdef SIDEMU_OLD_WAVE50
01123         ubyte makeSIDsData1[17*8] =
01124         {
01125                 0x00,0x00,0x00,0x00,0x00,0x40,0x60,0x7f,                // 0x78
01126                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 0x80
01127                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 0x88
01128                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 0x90
01129                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,                // 0x98
01130                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 0xa0
01131                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,                // 0xa8
01132                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,                // 0xb0
01133                 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0xbf,                // 0xb8
01134                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                // 0xc0
01135                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,                // 0xc8
01136                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,                // 0xd0
01137                 0x00,0x00,0x00,0xc0,0x00,0xc0,0xc0,0xdf,                // 0xd8
01138                 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,                // 0xe0
01139                 0x00,0x00,0x00,0xc0,0xe0,0xe0,0xe0,0xef,                // 0xe8
01140                 0x00,0x00,0x80,0xe0,0x80,0xe0,0xe0,0xf7,                // 0xf0
01141                 0x80,0xe0,0xf0,0xfb,0xf0,0xfd,0xfe,0xff         // 0xf8
01142         };
01143         k = 0;
01144         for ( i = 0; i < 4096; i++ )
01145         {
01146                 ubyte tmp = triangleTable[i];
01147                 if (tmp < 0x78)
01148                 {
01149                         tmp = 0;
01150                 }
01151                 else
01152                 {
01153                         tmp = makeSIDsData1[tmp-0x78];
01154                 }
01155                 waveform50[k++] = tmp;
01156         }
01157 #else
01158         if ( isNewSID )
01159         {
01160                 for ( i = 0; i < 4096; i++ )
01161                         waveform50[i] = waveform50_8580[i];
01162         }
01163         else
01164         {
01165                 int dest = 0;
01166                 for ( i = 0; i < 512; i++ )
01167                         for ( j = 0; j < 8; j++ )
01168                                 waveform50[dest++] = waveform50_6581[i];
01169         }
01170 #endif
01171 
01172         for ( i = 4096; i < 8192; i++ )
01173         {
01174 #ifndef LESS_CODE_BUT_ABIT_SLOWER
01175                 waveform50[i] = 0;
01176                 waveform60_8580[i] = 0;
01177                 waveform70_8580[i] = 0;
01178 #endif
01179 
01180         }
01181         
01182         if ( isNewSID )
01183         {
01184                 sidModeNormalTable[3] = &sidEmu::sidMode30;
01185                 sidModeNormalTable[6] = &sidEmu::sidMode60;
01186                 sidModeNormalTable[7] = &sidEmu::sidMode70;
01187                 sidModeRingTable[7] = &sidEmu::sidMode74;
01188         }
01189         else
01190         {
01191                 sidModeNormalTable[3] = &sidEmu::sidMode30;
01192                 sidModeNormalTable[6] = &sidEmu::sidMode60;
01193                 sidModeNormalTable[7] = &sidEmu::sidMode00;
01194                 sidModeRingTable[7] = &sidEmu::sidMode00;
01195         }
01196 
01197 #if defined(LARGE_NOISE_TABLE)
01198         udword ni;
01199         for (ni = 0; ni < sizeof(noiseTableLSB); ni++)
01200         {
01201                 noiseTableLSB[ni] = (ubyte)
01202                         (((ni >> (13-4)) & 0x10) |
01203                          ((ni >> (11-3)) & 0x08) |
01204                          ((ni >> (7-2)) & 0x04) |
01205                          ((ni >> (4-1)) & 0x02) |
01206                          ((ni >> (2-0)) & 0x01));
01207         }
01208         for (ni = 0; ni < sizeof(noiseTableMSB); ni++)
01209         {
01210                 noiseTableMSB[ni] = (ubyte)
01211                         (((ni << (7-(22-16))) & 0x80) |
01212                          ((ni << (6-(20-16))) & 0x40) |
01213                          ((ni << (5-(16-16))) & 0x20));
01214         }
01215 #else
01216         udword ni;
01217         for (ni = 0; ni < sizeof(noiseTableLSB); ni++)
01218         {
01219                 noiseTableLSB[ni] = (ubyte)
01220                         (((ni >> (7-2)) & 0x04) |
01221                          ((ni >> (4-1)) & 0x02) |
01222                          ((ni >> (2-0)) & 0x01));
01223         }
01224         for (ni = 0; ni < sizeof(noiseTableMID); ni++)
01225         {
01226                 noiseTableMID[ni] = (ubyte)
01227                         (((ni >> (13-8-4)) & 0x10) |
01228                          ((ni << (3-(11-8))) & 0x08));
01229         }
01230         for (ni = 0; ni < sizeof(noiseTableMSB); ni++)
01231         {
01232                 noiseTableMSB[ni] = (ubyte)
01233                         (((ni << (7-(22-16))) & 0x80) |
01234                          ((ni << (6-(20-16))) & 0x40) |
01235                          ((ni << (5-(16-16))) & 0x20));
01236         }
01237 #endif
01238 }
01239 
01240 
01241 void sidEmu::sidEmuConfigure(const struct emuConfig& aEmuConfig)
01242 {
01243         sidEmuSetClockSpeed(aEmuConfig.clockSpeed);  // set clock speed
01244 
01245         PCMfreq = aEmuConfig.frequency;
01246 //      PCMsid = (udword)(PCMfrequency * (16777216.0 / C64_fClockSpeed)); // This is the original (working) __fixunsdfsi
01247 //      PCMsidNoise = (udword)((C64_fClockSpeed*256.0)/PCMfrequency);
01248 //      PCMsid = (sdword)(PCMfrequency * (16777216.0 / C64_fClockSpeed)); // this is also safe
01249 //      PCMsidNoise = (sdword)((C64_fClockSpeed*256.0)/PCMfrequency);
01250         PCMsid = (udword)(aEmuConfig.frequency * (16777216 / C64_clockSpeed)); //TODO! use fClockSpeed instead ! 
01251         PCMsidNoise = (udword)((C64_clockSpeed*256) / aEmuConfig.frequency);
01252 
01253         sidEmuChangeReplayingSpeed();       // depends on frequency
01254         iTheSampler->sampleEmuInit(this);   // depends on clock speed + frequency
01255         
01256         filterEnabled = aEmuConfig.emulateFilter;
01257         initWaveformTables(aEmuConfig.mos8580);
01258         
01259         iTheEnvelope->enveEmuInit(PCMfreq, aEmuConfig.measuredVolume);
01260 }
01261 
01262 
01263 // Reset.
01264 
01265 bool sidEmu::sidEmuReset()
01266 {
01267         clearSidOperator( &optr1 );
01268         iTheEnvelope->enveEmuResetOperator( &optr1 );
01269         clearSidOperator( &optr2 );
01270         iTheEnvelope->enveEmuResetOperator( &optr2 );
01271         clearSidOperator( &optr3 );
01272         iTheEnvelope->enveEmuResetOperator( &optr3 );
01273         
01274         optr1.modulator = &optr3;
01275         optr3.carrier = &optr1;
01276         optr1.filtVoiceMask = 1;
01277         
01278         optr2.modulator = &optr1;
01279         optr1.carrier = &optr2;
01280         optr2.filtVoiceMask = 2;
01281         
01282         optr3.modulator = &optr2;
01283         optr2.carrier = &optr3;
01284         optr3.filtVoiceMask = 4;
01285         
01286         // Used for detecting changes of the GATE-bit (aka KEY-bit).
01287         // 6510-interpreter clears these before each call.
01288         iThe6510->sidKeysOff[4] = 
01289           (iThe6510->sidKeysOff[4+7] = 
01290            (iThe6510->sidKeysOff[4+14] = false));
01291         iThe6510->sidKeysOn[4] = 
01292           (iThe6510->sidKeysOn[4+7] = 
01293            (iThe6510->sidKeysOn[4+14] = false));
01294         
01295         iTheSampler->sampleEmuReset(this);
01296         
01297         filterType = (filterCurType = 0);
01298         filterValue = 0;
01299         filterDy = (filterResDy = 0);
01300         
01301         toFill = 0;
01302 #if defined(SIDEMU_TIME_COUNT)
01303         prevBufferLen = (scaledBufferLen = 0);
01304 #endif
01305         
01306         return true;
01307 }
01308 
01309 
01310 void sidEmu::clearSidOperator( struct sidOperator* pVoice )
01311 {
01312         pVoice->SIDfreq = 0;
01313         pVoice->SIDctrl = 0;
01314         pVoice->SIDAD = 0;
01315         pVoice->SIDSR = 0;
01316 
01317         pVoice->sync = false;
01318         
01319         pVoice->pulseIndex = (pVoice->newPulseIndex = (pVoice->SIDpulseWidth = 0));
01320         pVoice->curSIDfreq = (pVoice->curNoiseFreq = 0);
01321         
01322         pVoice->output = (pVoice->noiseOutput = 0);
01323         pVoice->filtIO = 0;
01324         
01325         pVoice->filtEnabled = false;
01326         pVoice->filtLow = (pVoice->filtRef = 0);
01327 
01328         pVoice->cycleLenCount = 0;
01329 #if defined(DIRECT_FIXPOINT)
01330         pVoice->cycleLen.l = (pVoice->cycleAddLen.l = 0);
01331 #else
01332         pVoice->cycleLen = (pVoice->cycleLenPnt = 0);
01333         pVoice->cycleAddLenPnt = 0;
01334 #endif
01335         
01336         pVoice->outProc = &sidEmu::waveCalcMute;
01337 
01338 #if defined(DIRECT_FIXPOINT)
01339         pVoice->waveStepAdd.l = (pVoice->waveStep.l = 0);
01340         pVoice->wavePre[0].len = (uword)(pVoice->wavePre[0].stp = 0);
01341         pVoice->wavePre[1].len = (uword)(pVoice->wavePre[1].stp = 0);
01342 #else
01343         pVoice->waveStep = 0;
01344         pVoice->waveStepAdd = 0;
01345         pVoice->waveStepPnt = 0;
01346         pVoice->waveStepAddPnt = 0;
01347         pVoice->wavePre[0].len = 0;
01348         pVoice->wavePre[0].stp = 0;
01349         pVoice->wavePre[0].pnt = 0;
01350         pVoice->wavePre[1].len = 0;
01351         pVoice->wavePre[1].stp = 0;
01352         pVoice->wavePre[1].pnt = 0;
01353 #endif
01354         pVoice->waveStepOld = 0;
01355 
01356 #if defined(DIRECT_FIXPOINT)
01357         pVoice->noiseReg.l = noiseSeed;
01358 #else
01359         pVoice->noiseReg = noiseSeed;
01360 #endif
01361         pVoice->noiseStepAdd = (pVoice->noiseStep = 0);
01362         pVoice->noiseIsLocked = false;
01363 }
01364 
01365 
01366 void sidEmu::sidEmuResetAutoPanning(int autoPanning)
01367 {
01368         doAutoPanning = (autoPanning!=SIDEMU_NONE);
01369         updateAutoPanning = false;
01370         apCount = 0;
01371         // Auto-panning see sidEmuSet(). Reset volume levels to default.
01372         if (doAutoPanning)
01373         {
01374                 optr1.gainLeft = (optr1.gainSource = 0xa080);
01375                 optr1.gainRight = (optr1.gainDest = 0x2080);
01376                 optr1.gainDirec = (optr1.gainLeft > optr1.gainRight);
01377                 optr1.gainLeftCentered = 0x8080;  // middle
01378                 optr1.gainRightCentered = 0x7f80;
01379                 
01380                 optr2.gainLeft = (optr2.gainSource = 0x2080);  // this one mirrored
01381                 optr2.gainRight = (optr2.gainDest = 0xa080);
01382                 optr2.gainDirec = (optr2.gainLeft > optr2.gainRight);
01383                 optr2.gainLeftCentered = 0x8080;  // middle
01384                 optr2.gainRightCentered = 0x7f80;
01385                 
01386                 optr3.gainLeft = (optr3.gainSource = 0xa080);
01387                 optr3.gainRight = (optr3.gainDest = 0x2080);
01388                 optr3.gainDirec = (optr3.gainLeft > optr3.gainRight);
01389                 optr3.gainLeftCentered = 0x8080;  // middle
01390                 optr3.gainRightCentered = 0x7f80;
01391                 
01392                 voice4_gainLeft = 0x8080;   // middle, not moving
01393                 voice4_gainRight = 0x7f80;
01394         }
01395 }
01396 
01397 
01398 void sidEmu::sidEmuSetVoiceVolume(int voice, uword leftLevel, uword rightLevel, uword total)
01399 {
01400         leftLevel *= total;
01401         leftLevel >>= 8;
01402         rightLevel *= total;
01403         rightLevel >>= 8;
01404         uword centeredLeftLevel = (0x80*total)>>8;
01405         uword centeredRightLevel = (0x7f*total)>>8;
01406         // Signed 8-bit samples will be added to base array index. 
01407         // So middle must be 0x80.
01408         // [-80,-81,...,-FE,-FF,0,1,...,7E,7F]
01409         uword leftIndex = 0x0080 + (leftLevel<<8);
01410         uword rightIndex = 0x0080 + (rightLevel<<8);
01411         uword gainLeftCentered = 0x0080 + (centeredLeftLevel<<8);
01412         uword gainRightCentered = 0x0080 + (centeredRightLevel<<8);
01413         switch ( voice )
01414         {
01415          case 1:
01416                 {
01417                         optr1.gainLeft = leftIndex;
01418                         optr1.gainRight = rightIndex;
01419                         //
01420                         optr1.gainSource = leftIndex;
01421                         optr1.gainDest = rightIndex;
01422                         optr1.gainLeftCentered = gainLeftCentered;
01423                         optr1.gainRightCentered = gainRightCentered;
01424                         optr1.gainDirec = (optr1.gainLeft > optr1.gainDest);
01425                         break;
01426                 }
01427          case 2:
01428                 {
01429                         optr2.gainLeft = leftIndex;
01430                         optr2.gainRight = rightIndex;
01431                         //
01432                         optr2.gainSource = leftIndex;
01433                         optr2.gainDest = rightIndex;
01434                         optr2.gainLeftCentered = gainLeftCentered;
01435                         optr2.gainRightCentered = gainRightCentered;
01436                         optr2.gainDirec = (optr2.gainLeft > optr2.gainDest);
01437                         break;
01438                 }
01439          case 3:
01440                 {
01441                         optr3.gainLeft = leftIndex;
01442                         optr3.gainRight = rightIndex;
01443                         //
01444                         optr3.gainSource = leftIndex;
01445                         optr3.gainDest = rightIndex;
01446                         optr3.gainLeftCentered = gainLeftCentered;
01447                         optr3.gainRightCentered = gainRightCentered;
01448                         optr3.gainDirec = (optr3.gainLeft > optr3.gainDest);
01449                         break;
01450                 }
01451          case 4:
01452                 {
01453                         voice4_gainLeft = leftIndex;
01454                         voice4_gainRight = rightIndex;
01455                         break;
01456                 }
01457          default:
01458                 {
01459                         break;
01460                 }
01461         }
01462 }
01463 
01464 
01465 uword sidEmu::sidEmuReturnVoiceVolume( int voice )
01466 {
01467         uword left = 0;
01468         uword right = 0;
01469         switch ( voice )
01470         {
01471          case 1:
01472                 {
01473                         left = optr1.gainLeft;
01474                         right = optr1.gainRight;
01475                         break;
01476                 }
01477          case 2:
01478                 {
01479                         left = optr2.gainLeft;
01480                         right = optr2.gainRight;
01481                         break;
01482                 }
01483          case 3:
01484                 {
01485                         left = optr3.gainLeft;
01486                         right = optr3.gainRight;
01487                         break;
01488                 }
01489          case 4:
01490                 {
01491                         left = voice4_gainLeft;
01492                         right = voice4_gainRight;
01493                         break;
01494                 }
01495          default:
01496                 {
01497                         break;
01498                 }
01499         }
01500         return (uword)(left&0xff00)|(right>>8);
01501 }
01502 
01503 
01504 sidEmu::sidEmu(emuEngine* aEmuEngine)
01508         :calls(50)
01509         ,fastForwardFactor(128)
01510         ,sidtuneClockSpeed(985248)
01511         ,C64_clockSpeed(985248)
01512         ,filterEnabled(true)
01513         ,filterType(0)
01514         ,filterCurType(0)
01515         ,iTheEmuEngine(aEmuEngine)
01516         {
01517         CTOR(sidEmu);
01518 
01519         triangleTable = new ubyte[4096];
01520         sawtoothTable = new ubyte[4096];
01521         squareTable   = new ubyte[2*4096];
01522 
01523 #ifdef LESS_CODE_BUT_ABIT_SLOWER
01524         waveform50 = new ubyte[1*4096]; // first half is data, last half is only zeros. Don't need to store these
01525 #else
01526         waveform50 = new ubyte[2*4096];
01527 #endif
01528 
01529 #if defined(LARGE_NOISE_TABLE)
01530         noiseTableMSB = new ubyte[1<<8];
01531         noiseTableLSB = new ubyte[1L<<16];
01532 #else
01533         noiseTableMSB = new ubyte[1<<8];
01534         noiseTableMID = new ubyte[1<<8];
01535         noiseTableLSB = new ubyte[1<<8];
01536 #endif
01537 
01538     // MOS-8580, MOS-6581 (no 70)
01539         sidModeNormalTable[0]  = &sidEmu::sidMode00;
01540         sidModeNormalTable[1]  = &sidEmu::sidMode10;
01541         sidModeNormalTable[2]  = &sidEmu::sidMode20;
01542         sidModeNormalTable[3]  = &sidEmu::sidMode30;
01543         sidModeNormalTable[4]  = &sidEmu::sidMode40;
01544         sidModeNormalTable[5]  = &sidEmu::sidMode50;
01545         sidModeNormalTable[6]  = &sidEmu::sidMode60;
01546         sidModeNormalTable[7]  = &sidEmu::sidMode70;
01547         sidModeNormalTable[8]  = &sidEmu::sidMode80;
01548         sidModeNormalTable[9]  = &sidEmu::sidModeLock;
01549         sidModeNormalTable[10] = &sidEmu::sidModeLock;
01550         sidModeNormalTable[11] = &sidEmu::sidModeLock;
01551         sidModeNormalTable[12] = &sidEmu::sidModeLock;
01552         sidModeNormalTable[13] = &sidEmu::sidModeLock;
01553         sidModeNormalTable[14] = &sidEmu::sidModeLock;
01554         sidModeNormalTable[15] = &sidEmu::sidModeLock;
01555         
01556     // MOS-8580, MOS-6581 (no 74)
01557         sidModeRingTable[0]  = &sidEmu::sidMode00;
01558         sidModeRingTable[1]  = &sidEmu::sidMode14;
01559         sidModeRingTable[2]  = &sidEmu::sidMode00;
01560         sidModeRingTable[3]  = &sidEmu::sidMode34;
01561         sidModeRingTable[4]  = &sidEmu::sidMode00;
01562         sidModeRingTable[5]  = &sidEmu::sidMode54;
01563         sidModeRingTable[6]  = &sidEmu::sidMode00;
01564         sidModeRingTable[7]  = &sidEmu::sidMode74;
01565         sidModeRingTable[8]  = &sidEmu::sidModeLock;
01566         sidModeRingTable[9]  = &sidEmu::sidModeLock;
01567         sidModeRingTable[10] = &sidEmu::sidModeLock;
01568         sidModeRingTable[11] = &sidEmu::sidModeLock;
01569         sidModeRingTable[12] = &sidEmu::sidModeLock;
01570         sidModeRingTable[13] = &sidEmu::sidModeLock;
01571         sidModeRingTable[14] = &sidEmu::sidModeLock;
01572         sidModeRingTable[15] = &sidEmu::sidModeLock;
01573 
01574         iTheEnvelope = new Envelope();
01575         iTheSampler = new Sample(aEmuEngine->iThe6510);
01576 
01577 // clear the memory
01578         memset(&optr1, sizeof(sidOperator), 0);
01579         memset(&optr2, sizeof(sidOperator), 0);
01580         memset(&optr3, sizeof(sidOperator), 0);
01581         
01582         iThe6510 = aEmuEngine->iThe6510;
01583         c64mem1 = iThe6510->c64mem1;
01584         c64mem2 = iThe6510->c64mem2;
01585         
01586         }
01587 
01588 
01589 sidEmu::~sidEmu()
01593         {
01594     DTOR(sidEmu);
01595 
01596         delete triangleTable;
01597         delete sawtoothTable;
01598         delete squareTable;
01599 
01600         delete waveform50;
01601         
01602 #if defined(LARGE_NOISE_TABLE)
01603         delete noiseTableMSB;
01604         delete noiseTableLSB;
01605 #else
01606         delete noiseTableMSB;
01607         delete noiseTableMID;
01608         delete noiseTableLSB;
01609 #endif
01610 
01611         delete iTheEnvelope;
01612         delete iTheSampler;
01613         
01614         }
01615 
01616 

Generated on Tue Feb 8 04:13:56 2005 for Esidplay by doxygen 1.3.3