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

SID.cpp

Go to the documentation of this file.
00001 /*
00002  *  SID.cpp - 6581 emulation
00003  *
00004  *  Frodo (C) 1994-1997 Christian Bauer
00005  *
00006 
00007  *
00008  * Incompatibilities:
00009  * ------------------
00010  *
00011  *  - Lots of empirically determined constants in the filter calculations
00012  *  - Voice 3 cannot be muted
00013  */
00014 
00015 #include "sysdeps.h"
00016 #include <math.h>
00017 
00018 #include "SID.h"
00019 #include "Prefs.h"
00020 
00021 #ifdef __BEOS__
00022 #include <MediaKit.h>
00023 #endif
00024 
00025 #ifdef AMIGA
00026 #include <exec/types.h>
00027 #include <utility/hooks.h>
00028 #include <devices/ahi.h>
00029 #define USE_FIXPOINT_MATHS
00030 #define FIXPOINT_PREC 16        // number of fractional bits used in fixpoint representation
00031 #define PRECOMPUTE_RESONANCE
00032 #define ldSINTAB 9                      // size of sinus table (0 to 90 degrees)
00033 #endif
00034 
00035 #include "C64.h"
00036 
00037 #ifdef SUN
00038 extern "C" {
00039         #include <sys/audioio.h>
00040 }
00041 #endif
00042 
00043 #ifdef __hpux
00044 extern "C" {
00045         #include <sys/audio.h>
00046 }
00047 #endif
00048 
00049 #ifdef __mac__
00050 #include <Sound.h>
00051 #define M_PI 3.14159265358979323846
00052 #endif
00053 
00054 #ifdef WIN32
00055 class DigitalPlayer;
00056 #endif
00057 
00058 #ifdef __riscos__
00059 #include "ROLib.h"
00060 # ifndef M_PI
00061 # define M_PI 3.14159265358979323846
00062 # endif
00063 #define USE_FIXPOINT_MATHS
00064 #define FIXPOINT_PREC 16        // number of fractional bits used in fixpoint representation
00065 #define PRECOMPUTE_RESONANCE
00066 #define ldSINTAB 9                      // size of sinus table (0 to 90 degrees)
00067 #endif
00068 
00069 #ifdef __SYMBIAN32__
00070 #define USE_FIXPOINT_MATHS
00071 #define FIXPOINT_PREC 16        // number of fractional bits used in fixpoint representation
00072 #define PRECOMPUTE_RESONANCE
00073 #define ldSINTAB 9                      // size of sinus table (0 to 90 degrees)
00074 
00075 #include "VIC.h"
00076 #ifndef __ER6__
00077 #include <d32snd.h>
00078 #else
00079 #include <mda/common/audio.h>
00080 #include <mdaaudiooutputstream.h>
00081 #endif // __ER6__
00082 
00083 #endif // __SYMBIAN32__
00084 
00085 
00086 #ifdef USE_FIXPOINT_MATHS
00087 #include "FixPoint.i"
00088 #endif
00089 
00090 
00091 /*
00092  *  Resonance frequency polynomials
00093  */
00094 
00095 #define CALC_RESONANCE_LP(f) (227.755\
00096                                 - 1.7635 * f\
00097                                 - 0.0176385 * f * f\
00098                                 + 0.00333484 * f * f * f\
00099                                 - 9.05683E-6 * f * f * f * f)
00100 
00101 #define CALC_RESONANCE_HP(f) (366.374\
00102                                 - 14.0052 * f\
00103                                 + 0.603212 * f * f\
00104                                 - 0.000880196 * f * f * f)
00105 
00106 
00107 
00108 
00112 MOS6581::MOS6581(C64 *c64) : the_c64(c64), ThePrefs(c64->ThePrefs)
00113 {
00114         __CHECK_NULL(c64);
00115 
00116         the_renderer = NULL;
00117         for (int i=0; i<32; i++)
00118                 regs[i] = 0;
00119 
00120         // Open the renderer
00121         open_close_renderer(SIDTYPE_NONE, ThePrefs.SIDType);
00122 
00123         CTOR(MOS6581);
00124 }
00125 
00126 
00130 MOS6581::~MOS6581()
00131 {
00132         // Close the renderer
00133         open_close_renderer(ThePrefs.SIDType, SIDTYPE_NONE);
00134 
00135         DTOR(MOS6581);
00136 }
00137 
00138 
00142 void MOS6581::Reset(void)
00143 {
00144         for (int i=0; i<32; i++)
00145                 regs[i] = 0;
00146         last_sid_byte = 0;
00147 
00148         // Reset the renderer
00149         if (the_renderer != NULL)
00150                 the_renderer->Reset();
00151 
00152         ELOG1(_L8("SID reset\n"));
00153 }
00154 
00155 
00156 /*
00157  *  Preferences may have changed
00158  */
00159 
00160 void MOS6581::NewPrefs(Prefs *prefs)
00161 {
00162         open_close_renderer(ThePrefs.SIDType, prefs->SIDType);
00163         if (the_renderer != NULL)
00164                 the_renderer->NewPrefs(prefs);
00165 }
00166 
00167 
00168 /*
00169  *  Pause sound output
00170  */
00171 
00172 void MOS6581::PauseSound(void)
00173 {
00174         if (the_renderer != NULL)
00175                 the_renderer->Pause();
00176 }
00177 
00178 
00179 /*
00180  *  Resume sound output
00181  */
00182 
00183 void MOS6581::ResumeSound(void)
00184 {
00185         if (the_renderer != NULL)
00186                 the_renderer->Resume();
00187 }
00188 
00189 
00190 /*
00191  *  Get SID state
00192  */
00193 
00194 void MOS6581::GetState(MOS6581State *ss)
00195 {
00196         ss->freq_lo_1 = regs[0];
00197         ss->freq_hi_1 = regs[1];
00198         ss->pw_lo_1 = regs[2];
00199         ss->pw_hi_1 = regs[3];
00200         ss->ctrl_1 = regs[4];
00201         ss->AD_1 = regs[5];
00202         ss->SR_1 = regs[6];
00203 
00204         ss->freq_lo_2 = regs[7];
00205         ss->freq_hi_2 = regs[8];
00206         ss->pw_lo_2 = regs[9];
00207         ss->pw_hi_2 = regs[10];
00208         ss->ctrl_2 = regs[11];
00209         ss->AD_2 = regs[12];
00210         ss->SR_2 = regs[13];
00211 
00212         ss->freq_lo_3 = regs[14];
00213         ss->freq_hi_3 = regs[15];
00214         ss->pw_lo_3 = regs[16];
00215         ss->pw_hi_3 = regs[17];
00216         ss->ctrl_3 = regs[18];
00217         ss->AD_3 = regs[19];
00218         ss->SR_3 = regs[20];
00219 
00220         ss->fc_lo = regs[21];
00221         ss->fc_hi = regs[22];
00222         ss->res_filt = regs[23];
00223         ss->mode_vol = regs[24];
00224 
00225         ss->pot_x = 0xff;
00226         ss->pot_y = 0xff;
00227         ss->osc_3 = 0;
00228         ss->env_3 = 0;
00229 }
00230 
00231 
00232 /*
00233  *  Restore SID state
00234  */
00235 
00236 void MOS6581::SetState(MOS6581State *ss)
00237 {
00238         regs[0] = ss->freq_lo_1;
00239         regs[1] = ss->freq_hi_1;
00240         regs[2] = ss->pw_lo_1;
00241         regs[3] = ss->pw_hi_1;
00242         regs[4] = ss->ctrl_1;
00243         regs[5] = ss->AD_1;
00244         regs[6] = ss->SR_1;
00245 
00246         regs[7] = ss->freq_lo_2;
00247         regs[8] = ss->freq_hi_2;
00248         regs[9] = ss->pw_lo_2;
00249         regs[10] = ss->pw_hi_2;
00250         regs[11] = ss->ctrl_2;
00251         regs[12] = ss->AD_2;
00252         regs[13] = ss->SR_2;
00253 
00254         regs[14] = ss->freq_lo_3;
00255         regs[15] = ss->freq_hi_3;
00256         regs[16] = ss->pw_lo_3;
00257         regs[17] = ss->pw_hi_3;
00258         regs[18] = ss->ctrl_3;
00259         regs[19] = ss->AD_3;
00260         regs[20] = ss->SR_3;
00261 
00262         regs[21] = ss->fc_lo;
00263         regs[22] = ss->fc_hi;
00264         regs[23] = ss->res_filt;
00265         regs[24] = ss->mode_vol;
00266 
00267         // Stuff the new register values into the renderer
00268         if (the_renderer != NULL)
00269                 for (int i=0; i<25; i++)
00270                         the_renderer->WriteRegister(i, regs[i]);
00271 }
00272 
00273 
00278 #if defined(__SYMBIAN32__)
00279 const uint32 SAMPLE_FREQ = 8000;        // Sample output frequency in Hz
00280 #elif defined(AMIGA) || defined(__riscos__)
00281 const uint32 SAMPLE_FREQ = 22050;       // Sample output frequency in Hz
00282 #else
00283 const uint32 SAMPLE_FREQ = 44100;       // Sample output frequency in Hz
00284 #endif
00285 const uint32 SID_FREQ = 985248;         // SID frequency in Hz
00286 const uint32 CALC_FREQ = 50;                    // Frequency at which calc_buffer is called in Hz (should be 50Hz)
00287 const uint32 SID_CYCLES = SID_FREQ/SAMPLE_FREQ; // # of SID clocks per sample frame
00288 const int SAMPLE_BUF_SIZE = 0x138*2;// Size of buffer for sampled voice (double buffered)
00289 
00290 // SID waveforms (some of them :-)
00291 enum {
00292         WAVE_NONE,
00293         WAVE_TRI,
00294         WAVE_SAW,
00295         WAVE_TRISAW,
00296         WAVE_RECT,
00297         WAVE_TRIRECT,
00298         WAVE_SAWRECT,
00299         WAVE_TRISAWRECT,
00300         WAVE_NOISE
00301 };
00302 
00303 // EG states
00304 enum {
00305         EG_IDLE,
00306         EG_ATTACK,
00307         EG_DECAY,
00308         EG_RELEASE
00309 };
00310 
00311 // Filter types
00312 enum {
00313         FILT_NONE,
00314         FILT_LP,
00315         FILT_BP,
00316         FILT_LPBP,
00317         FILT_HP,
00318         FILT_NOTCH,
00319         FILT_HPBP,
00320         FILT_ALL
00321 };
00322 
00323 // Structure for one voice
00324 struct DRVoice {
00325         int wave;               // Selected waveform
00326         int eg_state;   // Current state of EG
00327         DRVoice *mod_by;        // Voice that modulates this one
00328         DRVoice *mod_to;        // Voice that is modulated by this one
00329 
00330         uint32 count;   // Counter for waveform generator, 8.16 fixed
00331         uint32 add;             // Added to counter in every frame
00332 
00333         uint16 freq;            // SID frequency value
00334         uint16 pw;              // SID pulse-width value
00335 
00336         uint32 a_add;   // EG parameters
00337         uint32 d_sub;
00338         uint32 s_level;
00339         uint32 r_sub;
00340         uint32 eg_level;        // Current EG level, 8.16 fixed
00341 
00342         uint32 noise;   // Last noise generator output value
00343 
00344         bool gate;              // EG gate bit
00345         bool ring;              // Ring modulation bit
00346         bool test;              // Test bit
00347         bool filter;    // Flag: Voice filtered
00348 
00349                                         // The following bit is set for the modulating
00350                                         // voice, not for the modulated one (as the SID bits)
00351         bool sync;              // Sync modulation bit
00352 };
00353 
00354 
00358 class DigitalRenderer : public SIDRenderer
00359 #ifdef __ER6__
00360                                           ,public SidDebugData
00361                                           ,public MMdaAudioOutputStreamCallback
00362 #endif
00363 {
00364 public:
00365         DigitalRenderer(C64 *c64);
00366         virtual ~DigitalRenderer();
00367 
00368         virtual void Reset(void);
00369         virtual void EmulateLine(void);
00370         virtual void WriteRegister(uint16 adr, uint8 byte);
00371         virtual void NewPrefs(Prefs *prefs);
00372         virtual void Pause(void);
00373         virtual void Resume(void);
00374 
00375 private:
00376         void init_sound(void);
00377         void calc_filter(void);
00378 #if defined(__riscos__)
00379         void calc_buffer(uint8 *buf, long count);
00380 #else
00381         void calc_buffer(int16 *buf, long count);
00382 #endif
00383 
00384         bool ready;                                             // Flag: Renderer has initialized and is ready
00385         uint8 volume;                                   // Master volume
00386         bool v3_mute;                                   // Voice 3 muted
00387 
00388         uint16 TriTable[0x1000*2];      // Tables for certain waveforms
00389         static const uint16 TriSawTable[0x100];
00390         static const uint16 TriRectTable[0x100];
00391         static const uint16 SawRectTable[0x100];
00392         static const uint16 TriSawRectTable[0x100];
00393         static const uint32 EGTable[16];        // Increment/decrement values for all A/D/R settings
00394         static const uint8 EGDRShift[256]; // For exponential approximation of D/R
00395         static const int16 SampleTab[16]; // Table for sampled voice
00396 
00397         DRVoice voice[3];                               // Data for 3 voices
00398 
00399         uint8 f_type;                                   // Filter type
00400         uint8 f_freq;                                   // SID filter frequency (upper 8 bits)
00401         uint8 f_res;                                    // Filter resonance (0..15)
00402 #ifdef USE_FIXPOINT_MATHS
00403         FixPoint f_ampl;
00404         FixPoint d1, d2, g1, g2;
00405         int32 xn1, xn2, yn1, yn2;               // can become very large
00406         FixPoint sidquot;
00407 #ifdef PRECOMPUTE_RESONANCE
00408         FixPoint resonanceLP[256];
00409         FixPoint resonanceHP[256];
00410 #endif
00411 #else
00412         float f_ampl;                                   // IIR filter input attenuation
00413         float d1, d2, g1, g2;                   // IIR filter coefficients
00414         float xn1, xn2, yn1, yn2;               // IIR filter previous input/output signal
00415 #ifdef PRECOMPUTE_RESONANCE
00416         float resonanceLP[256];                 // shortcut for calc_filter
00417         float resonanceHP[256];
00418 #endif
00419 #endif
00420 
00421         uint8 sample_buf[SAMPLE_BUF_SIZE]; // Buffer for sampled voice
00422         int sample_in_ptr;                              // Index in sample_buf for writing
00423 
00424 #ifdef __BEOS__
00425         static bool stream_func(void *arg, char *buf, size_t count, void *header);
00426         BDACStream *the_stream;                 // Pointer to stream
00427         BSubscriber *the_sub;                   // Pointer to subscriber
00428         bool in_stream;                                 // Flag: Subscriber has entered stream
00429 #endif
00430 
00431 #ifdef AMIGA
00432         static void sub_invoc(void);    // Sound sub-process
00433         void sub_func(void);
00434         struct Process *sound_process;
00435         int quit_sig, pause_sig,
00436                 resume_sig, ahi_sig;            // Sub-process signals
00437         struct Task *main_task;                 // Main task
00438         int main_sig;                                   // Main task signals
00439         static ULONG sound_func(void);  // AHI callback
00440         struct MsgPort *ahi_port;               // Port and IORequest for AHI
00441         struct AHIRequest *ahi_io;
00442         struct AHIAudioCtrl *ahi_ctrl;  // AHI control structure
00443         struct AHISampleInfo sample[2]; // SampleInfos for double buffering
00444         struct Hook sf_hook;                    // Hook for callback function
00445         int play_buf;                                   // Number of buffer currently playing
00446 #endif
00447 
00448 #ifdef __linux__
00449         int devfd, sndbufsize, buffer_rate;
00450         int16 *sound_buffer;
00451 #endif
00452 
00453 #ifdef SUN
00454         int fd;
00455         audio_info status;
00456         uint_t sent_samples,delta_samples;
00457         WORD *sound_calc_buf;
00458 #endif
00459 
00460 #ifdef __hpux
00461         int fd;
00462         audio_status status;
00463         int16 * sound_calc_buf;
00464         int linecnt;
00465 #endif
00466 
00467 #ifdef __mac__
00468         SndChannelPtr chan1;
00469         SndDoubleBufferHeader myDblHeader;
00470         SndDoubleBufferPtr sampleBuffer1, sampleBuffer2;
00471         SCStatus myStatus;
00472         short sndbufsize;
00473         OSErr err;
00474 
00475         static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
00476 #endif
00477 
00478 #ifdef WIN32
00479 public:
00480         void VBlank(void);
00481 
00482 private:
00483         void StartPlayer(void);
00484         void StopPlayer(void);
00485 
00486         BOOL direct_sound;
00487         DigitalPlayer *ThePlayer;
00488         SWORD *sound_buffer;
00489         int to_output;
00490         int sb_pos;
00491         int divisor;
00492         int *lead;
00493         int lead_pos;
00494 #endif
00495 
00496 #ifdef __riscos__
00497         int linecnt, sndbufsize;
00498         uint8 *sound_buffer;
00499 #endif
00500 
00501 private: // methods
00502         uint8 sid_random();
00503 private: // members
00504         C64 *the_c64;                                   
00505 
00506 #ifndef GLOBAL_PREFS
00507         Prefs& ThePrefs;
00508 #endif
00509 
00510         uint32 seed;                    
00511 
00512 #ifdef __SYMBIAN32__
00513 
00514 #ifndef __ER6__
00515         RDevSound iDevSound;            
00516         HBufC8* iAlawBuffer;            
00517 #else // __ER6__
00518 
00519 public:
00520         // From MMdaAudioOutputStreamCallback
00521         void MaoscOpenComplete(TInt aError);
00522         void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer);
00523         void MaoscPlayComplete(TInt aError);
00524 
00525         void reset_sync(); // Reset audio sync
00526         void SetVolumeL(TInt aVolume); // Set audio volume
00527 
00528 public:
00529         CMdaAudioOutputStream* iStream;
00530         TMdaAudioDataSettings iSettings;
00531 
00532         // Audio sync variables
00533         TUint iStartPlayTickCount;
00534         TUint iCountSampleBlocksCopied;
00535         TInt iTickPeriod_ys;
00536         TBool iAudioStarvation;
00537         TPtrC8 sound_buffer_desc;
00538 
00539 #endif // __ER6__
00540         int16 *sound_buffer;            
00541 
00542     int divisor;
00543     int to_output;
00544     int buffer_pos;
00545 
00546  // moved from FixPoint.i to avoid global data
00547 inline void InitFixSinTab(void);
00548 inline FixPoint fixsin(FixPoint x);
00549 inline FixPoint fixcos(FixPoint x);
00550 FixPoint SinTable[(1<<ldSINTAB)];
00551 
00552 #endif // __SYMBIAN32__
00553 
00554 };
00555 
00559 uint8 DigitalRenderer::sid_random()
00560 {
00561         seed = seed * 1103515245 + 12345;
00562         return seed >> 16;
00563 }
00564 
00565 #ifndef EMUL_MOS8580
00566 // Sampled from a 6581R4
00567 const uint16 DigitalRenderer::TriSawTable[0x100] = {
00568         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00569         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00570         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00571         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00572         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00573         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00574         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00575         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
00576         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00577         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00578         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00579         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00580         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00581         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00582         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00583         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C,
00584         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00585         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00586         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00587         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00588         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00589         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00590         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00591         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
00592         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00593         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00594         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00595         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00596         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00597         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00598         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00599         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C
00600 };
00601 
00602 const uint16 DigitalRenderer::TriRectTable[0x100] = {
00603         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00604         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00605         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00606         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00607         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00608         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00609         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00610         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00611         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00612         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00613         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00614         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
00615         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00616         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
00617         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0,
00618         0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC,
00619         0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080,
00620         0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000,
00621         0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
00622         0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00623         0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
00624         0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00625         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00626         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00627         0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00628         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00629         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00630         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00631         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00632         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00633         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00634         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
00635 };
00636 
00637 const uint16 DigitalRenderer::SawRectTable[0x100] = {
00638         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00639         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00640         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00641         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00642         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00643         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00644         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00645         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00646         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00647         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00648         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00649         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00650         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00651         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00652         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00653         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878,
00654         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00655         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00656         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00657         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00658         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00659         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00660         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00661         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00662         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00663         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00664         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00665         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00666         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00667         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00668         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00669         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878
00670 };
00671 
00672 const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
00673         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00674         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00675         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00676         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00677         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00678         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00679         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00680         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00681         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00682         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00683         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00684         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00685         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00686         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00687         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00688         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00689         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00690         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00691         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00692         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00693         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00694         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00695         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00696         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00697         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00698         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00699         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00700         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00701         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00702         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00703         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00704         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
00705 };
00706 #else
00707 // Sampled from an 8580R5
00708 const uint16 DigitalRenderer::TriSawTable[0x100] = {
00709         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00710         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00711         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00712         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00713         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00714         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00715         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00716         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
00717         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00718         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00719         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00720         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00721         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00722         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00723         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00724         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x3C3C,
00725         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00726         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00727         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00728         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00729         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00730         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00731         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00732         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C,
00733         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00734         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00735         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00736         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00737         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00738         0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080,
00739         0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0,
00740         0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE
00741 };
00742 
00743 const uint16 DigitalRenderer::TriRectTable[0x100] = {
00744         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00745         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00746         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00747         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00748         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00749         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00750         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00751         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00752         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00753         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00754         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00755         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00756         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00757         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00758         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00759         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00760         0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0,
00761         0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0,
00762         0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080,
00763         0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000,
00764         0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000,
00765         0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00766         0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00767         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00768         0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000,
00769         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00770         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00771         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00772         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00773         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00774         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00775         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
00776 };
00777 
00778 const uint16 DigitalRenderer::SawRectTable[0x100] = {
00779         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00780         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00781         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00782         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00783         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00784         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00785         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00786         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00787         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00788         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00789         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00790         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00791         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00792         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00793         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00794         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00795         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00796         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00797         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00798         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00799         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00800         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
00801         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
00802         0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE,
00803         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
00804         0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
00805         0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
00806         0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC,
00807         0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0,
00808         0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC,
00809         0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4,
00810         0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF
00811 };
00812 
00813 const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
00814         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00815         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00816         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00817         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00818         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00819         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00820         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00821         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00822         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00823         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00824         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00825         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00826         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00827         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00828         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00829         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00830         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00831         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00832         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00833         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00834         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00835         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00836         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00837         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00838         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00839         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00840         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00841         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00842         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
00843         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
00844         0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0,
00845         0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC
00846 };
00847 #endif
00848 
00849 const uint32 DigitalRenderer::EGTable[16] = {
00850         (SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32,
00851         (SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95,
00852         (SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220,
00853         (SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313,
00854         (SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977,
00855         (SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126,
00856         (SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720,
00857         (SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251
00858 };
00859 
00860 const uint8 DigitalRenderer::EGDRShift[256] = {
00861         5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,
00862         3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
00863         2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
00864         2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,
00865         1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00866         1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
00867         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00868         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00869         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00870         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00871         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00872         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00873         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00874         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00875         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
00876         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
00877 };
00878 
00879 const int16 DigitalRenderer::SampleTab[16] = {
00880         0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777,
00881         0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff,
00882 };
00883 
00884 
00885 /*
00886  *  Constructor
00887  */
00888 
00889 DigitalRenderer::DigitalRenderer(C64 *c64)
00890         :the_c64(c64)
00891         ,ThePrefs(c64->ThePrefs)
00892         ,seed(1)
00893 {
00894         __CHECK_NULL(c64);
00895 
00896         CTOR(DigitalRenderer);
00897 
00898         // Link voices together
00899         voice[0].mod_by = &voice[2];
00900         voice[1].mod_by = &voice[0];
00901         voice[2].mod_by = &voice[1];
00902         voice[0].mod_to = &voice[1];
00903         voice[1].mod_to = &voice[2];
00904         voice[2].mod_to = &voice[0];
00905 
00906         // Calculate triangle table
00907         for (int i=0; i<0x1000; i++) {
00908                 TriTable[i] = (i << 4) | (i >> 8);
00909                 TriTable[0x1fff-i] = (i << 4) | (i >> 8);
00910         }
00911 
00912 #ifdef PRECOMPUTE_RESONANCE
00913 #ifdef USE_FIXPOINT_MATHS
00914         // slow floating point doesn't matter much on startup!
00915         for (int j=0; j<256; j++) {
00916           resonanceLP[j] = FixNo(CALC_RESONANCE_LP(j));
00917           resonanceHP[j] = FixNo(CALC_RESONANCE_HP(j));
00918         }
00919         // Pre-compute the quotient. No problem since int-part is small enough
00920         sidquot = (int32)((((double)SID_FREQ)*65536) / SAMPLE_FREQ);
00921         // compute lookup table for sin and cos
00922 //      InitFixSinTab();
00923 #else
00924         for (int j=0; j<256; j++) {
00925           resonanceLP[j] = CALC_RESONANCE_LP(j);
00926           resonanceHP[j] = CALC_RESONANCE_HP(j);
00927         }
00928 #endif
00929 #endif
00930 
00931 #ifdef USE_FIXPOINT_MATHS
00932         InitFixSinTab();
00933 #endif
00934 
00935         Reset();
00936 
00937         // System specific initialization
00938         init_sound();
00939 }
00940 
00941 
00942 /*
00943  *  Reset emulation
00944  */
00945 
00946 void DigitalRenderer::Reset(void)
00947 {
00948         volume = 0;
00949         v3_mute = false;
00950 
00951         for (int v=0; v<3; v++) {
00952                 voice[v].wave = WAVE_NONE;
00953                 voice[v].eg_state = EG_IDLE;
00954                 voice[v].count = voice[v].add = 0;
00955                 voice[v].freq = voice[v].pw = 0;
00956                 voice[v].eg_level = voice[v].s_level = 0;
00957                 voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0];
00958                 voice[v].gate = voice[v].ring = voice[v].test = false;
00959                 voice[v].filter = voice[v].sync = false;
00960         }
00961 
00962         f_type = FILT_NONE;
00963         f_freq = f_res = 0;
00964 #ifdef USE_FIXPOINT_MATHS
00965         f_ampl = FixNo(1);
00966         d1 = d2 = g1 = g2 = 0;
00967         xn1 = xn2 = yn1 = yn2 = 0;
00968 #else
00969         f_ampl = 1.0;
00970         d1 = d2 = g1 = g2 = 0.0;
00971         xn1 = xn2 = yn1 = yn2 = 0.0;
00972 #endif
00973 
00974         sample_in_ptr = 0;
00975         memset(sample_buf, 0, SAMPLE_BUF_SIZE);
00976 
00977         ELOG1(_L8("Digital renderer reset\n"));
00978 
00979 }
00980 
00981 
00982 /*
00983  *  Write to register
00984  */
00985 
00986 void DigitalRenderer::WriteRegister(uint16 adr, uint8 byte)
00987 {
00988         if (!ready)
00989                 return;
00990 
00991         int v = adr/7;  // Voice number
00992 
00993         switch (adr) {
00994                 case 0:
00995                 case 7:
00996                 case 14:
00997                         voice[v].freq = (voice[v].freq & 0xff00) | byte;
00998 #ifdef USE_FIXPOINT_MATHS
00999                         voice[v].add = sidquot.imul((int)voice[v].freq);
01000 #else
01001                         voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
01002 #endif
01003                         break;
01004 
01005                 case 1:
01006                 case 8:
01007                 case 15:
01008                         voice[v].freq = (voice[v].freq & 0xff) | (byte << 8);
01009 #ifdef USE_FIXPOINT_MATHS
01010                         voice[v].add = sidquot.imul((int)voice[v].freq);
01011 #else
01012                         voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
01013 #endif
01014                         break;
01015 
01016                 case 2:
01017                 case 9:
01018                 case 16:
01019                         voice[v].pw = (voice[v].pw & 0x0f00) | byte;
01020                         break;
01021 
01022                 case 3:
01023                 case 10:
01024                 case 17:
01025                         voice[v].pw = (voice[v].pw & 0xff) | ((byte & 0xf) << 8);
01026                         break;
01027 
01028                 case 4:
01029                 case 11:
01030                 case 18:
01031                         voice[v].wave = (byte >> 4) & 0xf;
01032                         if ((byte & 1) != voice[v].gate)
01033                                 if (byte & 1)   // Gate turned on
01034                                         voice[v].eg_state = EG_ATTACK;
01035                                 else                    // Gate turned off
01036                                         if (voice[v].eg_state != EG_IDLE)
01037                                                 voice[v].eg_state = EG_RELEASE;
01038                         voice[v].gate = byte & 1;
01039                         voice[v].mod_by->sync = byte & 2;
01040                         voice[v].ring = byte & 4;
01041                         if ((voice[v].test = byte & 8))
01042                                 voice[v].count = 0;
01043                         break;
01044 
01045                 case 5:
01046                 case 12:
01047                 case 19:
01048                         voice[v].a_add = EGTable[byte >> 4];
01049                         voice[v].d_sub = EGTable[byte & 0xf];
01050                         break;
01051 
01052                 case 6:
01053                 case 13:
01054                 case 20:
01055                         voice[v].s_level = (byte >> 4) * 0x111111;
01056                         voice[v].r_sub = EGTable[byte & 0xf];
01057                         break;
01058 
01059                 case 22:
01060                         if (byte != f_freq) {
01061                                 f_freq = byte;
01062                                 if (ThePrefs.SIDFilters)
01063                                         calc_filter();
01064                         }
01065                         break;
01066 
01067                 case 23:
01068                         voice[0].filter = byte & 1;
01069                         voice[1].filter = byte & 2;
01070                         voice[2].filter = byte & 4;
01071                         if ((byte >> 4) != f_res) {
01072                                 f_res = byte >> 4;
01073                                 if (ThePrefs.SIDFilters)
01074                                         calc_filter();
01075                         }
01076                         break;
01077 
01078                 case 24:
01079                         volume = byte & 0xf;
01080                         v3_mute = byte & 0x80;
01081                         if (((byte >> 4) & 7) != f_type) {
01082                                 f_type = (byte >> 4) & 7;
01083 #ifdef USE_FIXPOINT_MATHS
01084                                 xn1 = xn2 = yn1 = yn2 = 0;
01085 #else
01086                                 xn1 = xn2 = yn1 = yn2 = 0.0;
01087 #endif
01088                                 if (ThePrefs.SIDFilters)
01089                                         calc_filter();
01090                         }
01091                         break;
01092         }
01093 }
01094 
01095 
01096 /*
01097  *  Preferences may have changed
01098  */
01099 
01100 void DigitalRenderer::NewPrefs(Prefs *prefs)
01101 {
01102         calc_filter();
01103 
01104 #if defined(__SYMBIAN32__)
01105         if(!prefs)
01106                 return;
01107 #if !defined (__ER6__)
01108 
01109         TSoundCaps sndCaps;
01110         iDevSound.Caps(sndCaps);
01111         if(prefs->iVolume > sndCaps().iMaxVolume)
01112                 prefs->iVolume = sndCaps().iMaxVolume;
01113         else if(prefs->iVolume < 0)
01114                 prefs->iVolume = 0;
01115 
01116         TSoundConfig sndConfig;
01117         iDevSound.Config(sndConfig); // read the default config
01118 
01119         sndConfig().iVolumeValue = prefs->iVolume;
01120         
01121         const TInt ret = iDevSound.SetConfig(sndConfig);
01122         if(ret != KErrNone)
01123                 {
01124                 ELOG2(_L8("AUDIO: WARNING! Could not set config due to [%d]\n"), ret);
01125                 }
01126 
01127 #else
01128     // Set a new volume
01129     SetVolumeL(prefs->iVolume);
01130 
01131 #endif // !defined (__ER6__)
01132 #endif // __SYMBIAN32__
01133 }
01134 
01135 
01136 /*
01137  *  Calculate IIR filter coefficients
01138  */
01139 
01140 void DigitalRenderer::calc_filter(void)
01141 {
01142 #ifdef USE_FIXPOINT_MATHS
01143         FixPoint fr, arg;
01144 
01145         if (f_type == FILT_ALL)
01146         {
01147                 d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = FixNo(1); return;
01148         }
01149         else if (f_type == FILT_NONE)
01150         {
01151                 d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = 0; return;
01152         }
01153 #else
01154         float fr, arg;
01155 
01156         // Check for some trivial cases
01157         if (f_type == FILT_ALL) {
01158                 d1 = 0.0; d2 = 0.0;
01159                 g1 = 0.0; g2 = 0.0;
01160                 f_ampl = 1.0;
01161                 return;
01162         } else if (f_type == FILT_NONE) {
01163                 d1 = 0.0; d2 = 0.0;
01164                 g1 = 0.0; g2 = 0.0;
01165                 f_ampl = 0.0;
01166                 return;
01167         }
01168 #endif
01169 
01170         // Calculate resonance frequency
01171         if (f_type == FILT_LP || f_type == FILT_LPBP)
01172 #ifdef PRECOMPUTE_RESONANCE
01173                 fr = resonanceLP[f_freq];
01174 #else
01175                 fr = CALC_RESONANCE_LP(f_freq);
01176 #endif
01177         else
01178 #ifdef PRECOMPUTE_RESONANCE
01179                 fr = resonanceHP[f_freq];
01180 #else
01181                 fr = CALC_RESONANCE_HP(f_freq);
01182 #endif
01183 
01184 #ifdef USE_FIXPOINT_MATHS
01185         // explanations see below.
01186         arg = fr / (int)(SAMPLE_FREQ >> 1);
01187         if (arg > FixNo(0.99)) {arg = FixNo(0.99);}
01188         if (arg < FixNo(0.01)) {arg = FixNo(0.01);}
01189 
01190         g2 = FixNo(0.55) + FixNo(1.2) * arg * (arg - 1) + FixNo(0.0133333333) * (int)f_res;
01191 //      ELOG1(_L8("resonance freq 1\n"));
01192 
01193         g1 = FixNo(-2) * g2.sqrt() * fixcos(arg);
01194 
01195 //      ELOG1(_L8("resonance freq 2\n"));
01196 
01197         if (f_type == FILT_LPBP || f_type == FILT_HPBP) {g2 += FixNo(0.1);}
01198 
01199 //      ELOG1(_L8("resonance freq 3\n"));
01200 
01201         if (g1.abs() >= g2 + 1)
01202         {
01203           if (g1 > 0) {g1 = g2 + FixNo(0.99);}
01204           else {g1 = -(g2 + FixNo(0.99));}
01205         }
01206 
01207         switch (f_type)
01208         {
01209           case FILT_LPBP:
01210           case FILT_LP:
01211                 d1 = FixNo(2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 + g1 + g2); break;
01212           case FILT_HPBP:
01213           case FILT_HP:
01214                 d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break;
01215           case FILT_BP:
01216 //                ELOG1(_L8("FILT_BP 1\n"));
01217                 d1 = 0; d2 = FixNo(-1);
01218                 f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
01219                 break;
01220           case FILT_NOTCH:
01221 //                ELOG1(_L8("case FILT_NOTCH 1\n"));
01222                 d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1);
01223                 f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
01224                 break;
01225           default: break;
01226         }
01227 
01228 #else // USE_FIXPOINT_MATHS
01229 
01230         // Limit to <1/2 sample frequency, avoid div by 0 in case FILT_BP below
01231         arg = fr / (float)(SAMPLE_FREQ >> 1);
01232         if (arg > 0.99)
01233                 arg = 0.99;
01234         if (arg < 0.01)
01235                 arg = 0.01;
01236 
01237         // Calculate poles (resonance frequency and resonance)
01238         g2 = 0.55 + 1.2 * arg * arg - 1.2 * arg + (float)f_res * 0.0133333333;
01239         g1 = -2.0 * sqrt(g2) * cos(M_PI * arg);
01240 
01241         // Increase resonance if LP/HP combined with BP
01242         if (f_type == FILT_LPBP || f_type == FILT_HPBP)
01243                 g2 += 0.1;
01244 
01245         // Stabilize filter
01246         if (fabs(g1) >= g2 + 1.0)
01247                 if (g1 > 0.0)
01248                         g1 = g2 + 0.99;
01249                 else
01250                         g1 = -(g2 + 0.99);
01251 
01252         // Calculate roots (filter characteristic) and input attenuation
01253         switch (f_type) {
01254 
01255                 case FILT_LPBP:
01256                 case FILT_LP:
01257                         d1 = 2.0; d2 = 1.0;
01258                         f_ampl = 0.25 * (1.0 + g1 + g2);
01259                         break;
01260 
01261                 case FILT_HPBP:
01262                 case FILT_HP:
01263                         d1 = -2.0; d2 = 1.0;
01264                         f_ampl = 0.25 * (1.0 - g1 + g2);
01265                         break;
01266 
01267                 case FILT_BP:
01268                         d1 = 0.0; d2 = -1.0;
01269                         f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / sin(M_PI * arg);
01270                         break;
01271 
01272                 case FILT_NOTCH:
01273                         d1 = -2.0 * cos(M_PI * arg); d2 = 1.0;
01274                         f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / (sin(M_PI * arg));
01275                         break;
01276 
01277                 default:
01278                         break;
01279         }
01280 #endif // USE_FIXPOINT_MATHS
01281 }
01282 
01283 
01287 #if defined(__riscos__)
01288 void DigitalRenderer::calc_buffer(uint8 *buf, long count)
01289 #else
01290 void DigitalRenderer::calc_buffer(int16 *buf, long count)
01291 #endif
01292 {
01293         // Get filter coefficients, so the emulator won't change
01294         // them in the middle of our calculations
01295 #ifdef USE_FIXPOINT_MATHS
01296         FixPoint cf_ampl = f_ampl;
01297         FixPoint cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
01298 #else
01299         float cf_ampl = f_ampl;
01300         float cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
01301 #endif
01302 
01303 #ifdef __riscos__
01304         uint8 *LinToLog, *LogScale;
01305 #endif
01306 
01307         // Index in sample_buf for reading, 16.16 fixed
01308         uint32 sample_count = (sample_in_ptr + SAMPLE_BUF_SIZE/2) << 16;
01309 
01310 #ifdef __riscos__       // on RISC OS we have 8 bit logarithmic sound
01311         DigitalRenderer_GetTables(&LinToLog, &LogScale);        // get translation tables
01312 #else
01313 #ifdef __BEOS__
01314         count >>= 2;    // 16 bit stereo output, count is in bytes
01315 #else
01316         count >>= 1;    // 16 bit mono output, count is in bytes
01317 #endif
01318 #endif
01319         while (count--) {
01320                 int32 sum_output;
01321                 int32 sum_output_filter = 0;
01322 
01323                 // Get current master volume from sample buffer,
01324                 // calculate sampled voice
01325                 uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE];
01326                 sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ;
01327                 sum_output = SampleTab[master_volume] << 8;
01328 
01329                 // Loop for all three voices
01330                 for (int j=0; j<3; j++) {
01331                         DRVoice *v = &voice[j];
01332 
01333                         // Envelope generators
01334                         uint16 envelope;
01335 
01336                         switch (v->eg_state) {
01337                                 case EG_ATTACK:
01338                                         v->eg_level += v->a_add;
01339                                         if (v->eg_level > 0xffffff) {
01340                                                 v->eg_level = 0xffffff;
01341                                                 v->eg_state = EG_DECAY;
01342                                         }
01343                                         break;
01344                                 case EG_DECAY:
01345                                         if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
01346                                                 v->eg_level = v->s_level;
01347                                         else {
01348                                                 v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16];
01349                                                 if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
01350                                                         v->eg_level = v->s_level;
01351                                         }
01352                                         break;
01353                                 case EG_RELEASE:
01354                                         v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16];
01355                                         if (v->eg_level > 0xffffff) {
01356                                                 v->eg_level = 0;
01357                                                 v->eg_state = EG_IDLE;
01358                                         }
01359                                         break;
01360                                 case EG_IDLE:
01361                                         v->eg_level = 0;
01362                                         break;
01363                         }
01364                         envelope = (v->eg_level * master_volume) >> 20;
01365 
01366                         // Waveform generator
01367                         uint16 output;
01368 
01369                         if (!v->test)
01370                                 v->count += v->add;
01371 
01372                         if (v->sync && (v->count > 0x1000000))
01373                                 v->mod_to->count = 0;
01374 
01375                         v->count &= 0xffffff;
01376 
01377                         switch (v->wave) {
01378                                 case WAVE_TRI:
01379                                         if (v->ring)
01380                                                 output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11];
01381                                         else
01382                                                 output = TriTable[v->count >> 11];
01383                                         break;
01384                                 case WAVE_SAW:
01385                                         output = v->count >> 8;
01386                                         break;
01387                                 case WAVE_RECT:
01388                                         if (v->count > (uint32)(v->pw << 12))
01389                                                 output = 0xffff;
01390                                         else
01391                                                 output = 0;
01392                                         break;
01393                                 case WAVE_TRISAW:
01394                                         output = TriSawTable[v->count >> 16];
01395                                         break;
01396                                 case WAVE_TRIRECT:
01397                                         if (v->count > (uint32)(v->pw << 12))
01398                                                 output = TriRectTable[v->count >> 16];
01399                                         else
01400                                                 output = 0;
01401                                         break;
01402                                 case WAVE_SAWRECT:
01403                                         if (v->count > (uint32)(v->pw << 12))
01404                                                 output = SawRectTable[v->count >> 16];
01405                                         else
01406                                                 output = 0;
01407                                         break;
01408                                 case WAVE_TRISAWRECT:
01409                                         if (v->count > (uint32)(v->pw << 12))
01410                                                 output = TriSawRectTable[v->count >> 16];
01411                                         else
01412                                                 output = 0;
01413                                         break;
01414                                 case WAVE_NOISE:
01415                                         if (v->count > 0x100000) {
01416                                                 output = v->noise = sid_random() << 8;
01417                                                 v->count &= 0xfffff;
01418                                         } else
01419                                                 output = v->noise;
01420                                         break;
01421                                 default:
01422                                         output = 0x8000;
01423                                         break;
01424                         }
01425                         if (v->filter)
01426                                 sum_output_filter += (int16)(output ^ 0x8000) * envelope;
01427                         else
01428                                 sum_output += (int16)(output ^ 0x8000) * envelope;
01429                 }
01430 
01431                 // Filter
01432                 if (ThePrefs.SIDFilters) {
01433 #ifdef USE_FIXPOINT_MATHS
01434                         int32 xn = cf_ampl.imul(sum_output_filter);
01435                         int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2);
01436                         yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
01437                         sum_output_filter = yn;
01438 #else
01439                         float xn = (float)sum_output_filter * cf_ampl;
01440                         float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2;
01441                         yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
01442                         sum_output_filter = (int32)yn;
01443 #endif
01444                 }
01445 
01446                 // Write to buffer
01447 #ifdef __BEOS__
01448                 int16 audio_data = (sum_output + sum_output_filter) >> 10;
01449                 int val = *buf + audio_data;
01450                 if (val > 32767)
01451                         val = 32767;
01452                 if (val < -32768)
01453                         val = -32768;
01454                 *buf++ = val;
01455                 val = *buf + audio_data;
01456                 if (val > 32767)
01457                         val = 32767;
01458                 if (val < -32768)
01459                         val = -32768;
01460                 *buf++ = val;
01461 #elif defined(__riscos__)       // lookup in 8k (13bit) translation table
01462                 *buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff];
01463 #else
01464                 *buf++ = (sum_output + sum_output_filter) >> 10;
01465 #endif
01466         }
01467 }
01468 
01469 
01470 // Manufacturer independent sound is still just a dream...
01471 #if defined(__SYMBIAN32__) // must be before __linux__ in case of using the GnuPoc SDK
01472 #include "sid_epoc32.i"
01473 
01474 #elif defined(__BEOS__)
01475 #include "SID_Be.i"
01476 
01477 #elif defined(AMIGA)
01478 #include "SID_Amiga.i"
01479 
01480 #elif defined(__linux__)
01481 #include "SID_linux.i"
01482 
01483 #elif defined(SUN)
01484 #include "SID_sun.i"
01485 
01486 #elif defined(__hpux)
01487 #include "SID_hp.i"
01488 
01489 #elif defined(__mac__)
01490 #include "SID_mac.i"
01491 
01492 #elif defined(WIN32)
01493 #include "SID_WIN32.i"
01494 
01495 #elif defined(__riscos__)
01496 #include "SID_Acorn.i"
01497 
01498 #else   // No sound
01499 void DigitalRenderer::init_sound(void) {ready = false;}
01500 DigitalRenderer::~DigitalRenderer()
01501         {
01502         DTOR(DigitalRenderer);
01503         }
01504 void DigitalRenderer::EmulateLine(void) {}
01505 void DigitalRenderer::Pause(void) {}
01506 void DigitalRenderer::Resume(void) {}
01507 #endif
01508 
01509 
01510 /*
01511  *  Open/close the renderer, according to old and new prefs
01512  */
01513 
01514 void MOS6581::open_close_renderer(int old_type, int new_type)
01515 {
01516         if (old_type == new_type)
01517                 return;
01518 
01519         // Delete the old renderer
01520         delete the_renderer;
01521 
01522         // Create new renderer
01523         if (new_type == SIDTYPE_DIGITAL)
01524                 the_renderer = new DigitalRenderer(the_c64);
01525 
01526 #ifdef AMIGA
01527         else if (new_type == SIDTYPE_SIDCARD)
01528                 the_renderer = new SIDCardRenderer();
01529 #endif
01530         else
01531                 the_renderer = NULL;
01532 
01533         // Stuff the current register values into the new renderer
01534         if (the_renderer != NULL)
01535                 for (int i=0; i<25; i++)
01536                         the_renderer->WriteRegister(i, regs[i]);
01537 }

Generated on Tue Feb 8 04:08:10 2005 for E32frodo by doxygen 1.3.3