ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (21 years, 5 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * SID.cpp - 6581 emulation
3     *
4 cebix 1.2 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     /*
22     * Incompatibilities:
23     * ------------------
24     *
25     * - Lots of empirically determined constants in the filter calculations
26     * - Voice 3 cannot be muted
27     */
28    
29     #include "sysdeps.h"
30     #include <math.h>
31    
32     #include "SID.h"
33     #include "Prefs.h"
34    
35     #ifdef __BEOS__
36     #include <MediaKit.h>
37     #endif
38    
39     #ifdef AMIGA
40     #include <exec/types.h>
41     #include <utility/hooks.h>
42     #include <devices/ahi.h>
43     #define USE_FIXPOINT_MATHS
44     #define FIXPOINT_PREC 16 // number of fractional bits used in fixpoint representation
45     #define PRECOMPUTE_RESONANCE
46     #define ldSINTAB 9 // size of sinus table (0 to 90 degrees)
47     #endif
48    
49     #ifdef SUN
50     extern "C" {
51     #include <sys/audioio.h>
52     }
53     #endif
54    
55     #ifdef __hpux
56     extern "C" {
57     #include <sys/audio.h>
58     }
59     #endif
60    
61     #ifdef __mac__
62     #include <Sound.h>
63     #define M_PI 3.14159265358979323846
64     #endif
65    
66     #ifdef WIN32
67     class DigitalPlayer;
68     #endif
69    
70     #ifdef __riscos__
71     #include "ROLib.h"
72     # ifndef M_PI
73     # define M_PI 3.14159265358979323846
74     # endif
75     #define USE_FIXPOINT_MATHS
76     #define FIXPOINT_PREC 16 // number of fractional bits used in fixpoint representation
77     #define PRECOMPUTE_RESONANCE
78     #define ldSINTAB 9 // size of sinus table (0 to 90 degrees)
79     #endif
80    
81    
82     #ifdef USE_FIXPOINT_MATHS
83     #include "FixPoint.h"
84     #endif
85    
86    
87     /*
88     * Resonance frequency polynomials
89     */
90    
91     #define CALC_RESONANCE_LP(f) (227.755\
92     - 1.7635 * f\
93     - 0.0176385 * f * f\
94     + 0.00333484 * f * f * f\
95     - 9.05683E-6 * f * f * f * f)
96    
97     #define CALC_RESONANCE_HP(f) (366.374\
98     - 14.0052 * f\
99     + 0.603212 * f * f\
100     - 0.000880196 * f * f * f)
101    
102    
103     /*
104     * Random number generator for noise waveform
105     */
106    
107     static uint8 sid_random(void);
108     static uint8 sid_random(void)
109     {
110     static uint32 seed = 1;
111     seed = seed * 1103515245 + 12345;
112     return seed >> 16;
113     }
114    
115    
116     /*
117     * Constructor
118     */
119    
120     MOS6581::MOS6581(C64 *c64) : the_c64(c64)
121     {
122     the_renderer = NULL;
123     for (int i=0; i<32; i++)
124     regs[i] = 0;
125    
126     // Open the renderer
127     open_close_renderer(SIDTYPE_NONE, ThePrefs.SIDType);
128     }
129    
130    
131     /*
132     * Destructor
133     */
134    
135     MOS6581::~MOS6581()
136     {
137     // Close the renderer
138     open_close_renderer(ThePrefs.SIDType, SIDTYPE_NONE);
139     }
140    
141    
142     /*
143     * Reset the SID
144     */
145    
146     void MOS6581::Reset(void)
147     {
148     for (int i=0; i<32; i++)
149     regs[i] = 0;
150     last_sid_byte = 0;
151    
152     // Reset the renderer
153     if (the_renderer != NULL)
154     the_renderer->Reset();
155     }
156    
157    
158     /*
159     * Preferences may have changed
160     */
161    
162     void MOS6581::NewPrefs(Prefs *prefs)
163     {
164     open_close_renderer(ThePrefs.SIDType, prefs->SIDType);
165     if (the_renderer != NULL)
166     the_renderer->NewPrefs(prefs);
167     }
168    
169    
170     /*
171     * Pause sound output
172     */
173    
174     void MOS6581::PauseSound(void)
175     {
176     if (the_renderer != NULL)
177     the_renderer->Pause();
178     }
179    
180    
181     /*
182     * Resume sound output
183     */
184    
185     void MOS6581::ResumeSound(void)
186     {
187     if (the_renderer != NULL)
188     the_renderer->Resume();
189     }
190    
191    
192     /*
193     * Get SID state
194     */
195    
196     void MOS6581::GetState(MOS6581State *ss)
197     {
198     ss->freq_lo_1 = regs[0];
199     ss->freq_hi_1 = regs[1];
200     ss->pw_lo_1 = regs[2];
201     ss->pw_hi_1 = regs[3];
202     ss->ctrl_1 = regs[4];
203     ss->AD_1 = regs[5];
204     ss->SR_1 = regs[6];
205    
206     ss->freq_lo_2 = regs[7];
207     ss->freq_hi_2 = regs[8];
208     ss->pw_lo_2 = regs[9];
209     ss->pw_hi_2 = regs[10];
210     ss->ctrl_2 = regs[11];
211     ss->AD_2 = regs[12];
212     ss->SR_2 = regs[13];
213    
214     ss->freq_lo_3 = regs[14];
215     ss->freq_hi_3 = regs[15];
216     ss->pw_lo_3 = regs[16];
217     ss->pw_hi_3 = regs[17];
218     ss->ctrl_3 = regs[18];
219     ss->AD_3 = regs[19];
220     ss->SR_3 = regs[20];
221    
222     ss->fc_lo = regs[21];
223     ss->fc_hi = regs[22];
224     ss->res_filt = regs[23];
225     ss->mode_vol = regs[24];
226    
227     ss->pot_x = 0xff;
228     ss->pot_y = 0xff;
229     ss->osc_3 = 0;
230     ss->env_3 = 0;
231     }
232    
233    
234     /*
235     * Restore SID state
236     */
237    
238     void MOS6581::SetState(MOS6581State *ss)
239     {
240     regs[0] = ss->freq_lo_1;
241     regs[1] = ss->freq_hi_1;
242     regs[2] = ss->pw_lo_1;
243     regs[3] = ss->pw_hi_1;
244     regs[4] = ss->ctrl_1;
245     regs[5] = ss->AD_1;
246     regs[6] = ss->SR_1;
247    
248     regs[7] = ss->freq_lo_2;
249     regs[8] = ss->freq_hi_2;
250     regs[9] = ss->pw_lo_2;
251     regs[10] = ss->pw_hi_2;
252     regs[11] = ss->ctrl_2;
253     regs[12] = ss->AD_2;
254     regs[13] = ss->SR_2;
255    
256     regs[14] = ss->freq_lo_3;
257     regs[15] = ss->freq_hi_3;
258     regs[16] = ss->pw_lo_3;
259     regs[17] = ss->pw_hi_3;
260     regs[18] = ss->ctrl_3;
261     regs[19] = ss->AD_3;
262     regs[20] = ss->SR_3;
263    
264     regs[21] = ss->fc_lo;
265     regs[22] = ss->fc_hi;
266     regs[23] = ss->res_filt;
267     regs[24] = ss->mode_vol;
268    
269     // Stuff the new register values into the renderer
270     if (the_renderer != NULL)
271     for (int i=0; i<25; i++)
272     the_renderer->WriteRegister(i, regs[i]);
273     }
274    
275    
276     /**
277     ** Renderer for digital SID emulation (SIDTYPE_DIGITAL)
278     **/
279    
280     #if defined(AMIGA) || defined(__riscos__)
281     const uint32 SAMPLE_FREQ = 22050; // Sample output frequency in Hz
282     #else
283     const uint32 SAMPLE_FREQ = 44100; // Sample output frequency in Hz
284     #endif
285     const uint32 SID_FREQ = 985248; // SID frequency in Hz
286     const uint32 CALC_FREQ = 50; // Frequency at which calc_buffer is called in Hz (should be 50Hz)
287     const uint32 SID_CYCLES = SID_FREQ/SAMPLE_FREQ; // # of SID clocks per sample frame
288     const int SAMPLE_BUF_SIZE = 0x138*2;// Size of buffer for sampled voice (double buffered)
289    
290     // SID waveforms (some of them :-)
291     enum {
292     WAVE_NONE,
293     WAVE_TRI,
294     WAVE_SAW,
295     WAVE_TRISAW,
296     WAVE_RECT,
297     WAVE_TRIRECT,
298     WAVE_SAWRECT,
299     WAVE_TRISAWRECT,
300     WAVE_NOISE
301     };
302    
303     // EG states
304     enum {
305     EG_IDLE,
306     EG_ATTACK,
307     EG_DECAY,
308     EG_RELEASE
309     };
310    
311     // Filter types
312     enum {
313     FILT_NONE,
314     FILT_LP,
315     FILT_BP,
316     FILT_LPBP,
317     FILT_HP,
318     FILT_NOTCH,
319     FILT_HPBP,
320     FILT_ALL
321     };
322    
323     // Structure for one voice
324     struct DRVoice {
325     int wave; // Selected waveform
326     int eg_state; // Current state of EG
327     DRVoice *mod_by; // Voice that modulates this one
328     DRVoice *mod_to; // Voice that is modulated by this one
329    
330     uint32 count; // Counter for waveform generator, 8.16 fixed
331     uint32 add; // Added to counter in every frame
332    
333     uint16 freq; // SID frequency value
334     uint16 pw; // SID pulse-width value
335    
336     uint32 a_add; // EG parameters
337     uint32 d_sub;
338     uint32 s_level;
339     uint32 r_sub;
340     uint32 eg_level; // Current EG level, 8.16 fixed
341    
342     uint32 noise; // Last noise generator output value
343    
344     bool gate; // EG gate bit
345     bool ring; // Ring modulation bit
346     bool test; // Test bit
347     bool filter; // Flag: Voice filtered
348    
349     // The following bit is set for the modulating
350     // voice, not for the modulated one (as the SID bits)
351     bool sync; // Sync modulation bit
352     };
353    
354     // Renderer class
355     class DigitalRenderer : public SIDRenderer {
356     public:
357     #if defined(__BEOS__) || defined(__riscos__)
358     DigitalRenderer(C64 *c64);
359     #else
360     DigitalRenderer();
361     #endif
362     virtual ~DigitalRenderer();
363    
364     virtual void Reset(void);
365     virtual void EmulateLine(void);
366     virtual void WriteRegister(uint16 adr, uint8 byte);
367     virtual void NewPrefs(Prefs *prefs);
368     virtual void Pause(void);
369     virtual void Resume(void);
370    
371     private:
372     void init_sound(void);
373     void calc_filter(void);
374     #ifdef __riscos__
375     void calc_buffer(uint8 *buf, long count);
376     #else
377     void calc_buffer(int16 *buf, long count);
378     #endif
379    
380     bool ready; // Flag: Renderer has initialized and is ready
381     uint8 volume; // Master volume
382     bool v3_mute; // Voice 3 muted
383    
384     static uint16 TriTable[0x1000*2]; // Tables for certain waveforms
385     static const uint16 TriSawTable[0x100];
386     static const uint16 TriRectTable[0x100];
387     static const uint16 SawRectTable[0x100];
388     static const uint16 TriSawRectTable[0x100];
389     static const uint32 EGTable[16]; // Increment/decrement values for all A/D/R settings
390     static const uint8 EGDRShift[256]; // For exponential approximation of D/R
391     static const int16 SampleTab[16]; // Table for sampled voice
392    
393     DRVoice voice[3]; // Data for 3 voices
394    
395     uint8 f_type; // Filter type
396     uint8 f_freq; // SID filter frequency (upper 8 bits)
397     uint8 f_res; // Filter resonance (0..15)
398     #ifdef USE_FIXPOINT_MATHS
399     FixPoint f_ampl;
400     FixPoint d1, d2, g1, g2;
401     int32 xn1, xn2, yn1, yn2; // can become very large
402     FixPoint sidquot;
403     #ifdef PRECOMPUTE_RESONANCE
404     FixPoint resonanceLP[256];
405     FixPoint resonanceHP[256];
406     #endif
407     #else
408     float f_ampl; // IIR filter input attenuation
409     float d1, d2, g1, g2; // IIR filter coefficients
410     float xn1, xn2, yn1, yn2; // IIR filter previous input/output signal
411     #ifdef PRECOMPUTE_RESONANCE
412     float resonanceLP[256]; // shortcut for calc_filter
413     float resonanceHP[256];
414     #endif
415     #endif
416    
417     uint8 sample_buf[SAMPLE_BUF_SIZE]; // Buffer for sampled voice
418     int sample_in_ptr; // Index in sample_buf for writing
419    
420     #ifdef __BEOS__
421     static bool stream_func(void *arg, char *buf, size_t count, void *header);
422     C64 *the_c64; // Pointer to C64 object
423     BDACStream *the_stream; // Pointer to stream
424     BSubscriber *the_sub; // Pointer to subscriber
425     bool in_stream; // Flag: Subscriber has entered stream
426     #endif
427    
428     #ifdef AMIGA
429     static void sub_invoc(void); // Sound sub-process
430     void sub_func(void);
431     struct Process *sound_process;
432     int quit_sig, pause_sig,
433     resume_sig, ahi_sig; // Sub-process signals
434     struct Task *main_task; // Main task
435     int main_sig; // Main task signals
436     static ULONG sound_func(void); // AHI callback
437     struct MsgPort *ahi_port; // Port and IORequest for AHI
438     struct AHIRequest *ahi_io;
439     struct AHIAudioCtrl *ahi_ctrl; // AHI control structure
440     struct AHISampleInfo sample[2]; // SampleInfos for double buffering
441     struct Hook sf_hook; // Hook for callback function
442     int play_buf; // Number of buffer currently playing
443     #endif
444    
445     #ifdef __linux__
446     int devfd, sndbufsize, buffer_rate;
447     int16 *sound_buffer;
448     #endif
449    
450     #ifdef SUN
451     int fd;
452     audio_info status;
453     uint_t sent_samples,delta_samples;
454     WORD *sound_calc_buf;
455     #endif
456    
457     #ifdef __hpux
458     int fd;
459     audio_status status;
460     int16 * sound_calc_buf;
461     int linecnt;
462     #endif
463    
464     #ifdef __mac__
465     SndChannelPtr chan1;
466     SndDoubleBufferHeader myDblHeader;
467     SndDoubleBufferPtr sampleBuffer1, sampleBuffer2;
468     SCStatus myStatus;
469     short sndbufsize;
470     OSErr err;
471    
472     static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
473     #endif
474    
475     #ifdef WIN32
476     public:
477     void VBlank(void);
478    
479     private:
480     void StartPlayer(void);
481     void StopPlayer(void);
482    
483     BOOL direct_sound;
484     DigitalPlayer *ThePlayer;
485     SWORD *sound_buffer;
486     int to_output;
487     int sb_pos;
488     int divisor;
489     int *lead;
490     int lead_pos;
491     #endif
492    
493     #ifdef __riscos__
494     int linecnt, sndbufsize;
495     uint8 *sound_buffer;
496     C64 *the_c64;
497     #endif
498     };
499    
500     // Static data members
501     uint16 DigitalRenderer::TriTable[0x1000*2];
502    
503     #ifndef EMUL_MOS8580
504     // Sampled from a 6581R4
505     const uint16 DigitalRenderer::TriSawTable[0x100] = {
506     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
507     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
508     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
509     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
510     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
511     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
512     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
513     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
514     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
515     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
516     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
517     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
518     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
519     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
520     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
521     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C,
522     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
523     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
524     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
525     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
526     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
527     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
528     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
529     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
530     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
531     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
532     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
533     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
534     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
535     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
536     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
537     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C
538     };
539    
540     const uint16 DigitalRenderer::TriRectTable[0x100] = {
541     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
542     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
543     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
544     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
545     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
546     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
547     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
548     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
549     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
550     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
551     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
552     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
553     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
554     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
555     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0,
556     0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC,
557     0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080,
558     0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000,
559     0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
560     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
561     0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
562     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
563     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
564     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
565     0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
566     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
567     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
568     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
569     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
570     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
571     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
572     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
573     };
574    
575     const uint16 DigitalRenderer::SawRectTable[0x100] = {
576     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
577     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
578     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
579     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
580     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
581     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
582     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
583     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
584     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
585     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
586     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
587     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
588     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
589     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
590     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
591     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878,
592     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
593     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
594     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
595     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
596     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
597     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
598     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
599     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
600     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
601     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
602     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
603     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
604     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
605     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
606     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
607     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878
608     };
609    
610     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
611     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
612     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
613     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
614     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
615     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
616     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
617     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
618     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
619     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
620     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
621     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
622     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
623     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
624     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
625     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
626     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
627     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
628     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
629     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
630     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
631     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
632     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
633     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
634     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
635     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
636     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
637     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
638     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
639     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
640     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
641     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
642     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
643     };
644     #else
645     // Sampled from an 8580R5
646     const uint16 DigitalRenderer::TriSawTable[0x100] = {
647     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
648     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
649     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
650     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
651     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
652     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
653     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
654     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
655     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
656     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
657     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
658     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
659     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
660     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
661     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
662     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x3C3C,
663     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
664     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
665     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
666     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
667     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
668     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
669     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
670     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C,
671     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
672     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
673     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
674     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
675     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
676     0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080,
677     0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0,
678     0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE
679     };
680    
681     const uint16 DigitalRenderer::TriRectTable[0x100] = {
682     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
683     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
684     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
685     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
686     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
687     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
688     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
689     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
690     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
691     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
692     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
693     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
694     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
695     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
696     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
697     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
698     0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0,
699     0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0,
700     0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080,
701     0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000,
702     0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000,
703     0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
704     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
705     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
706     0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000,
707     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
708     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
709     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
710     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
711     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
712     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
713     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
714     };
715    
716     const uint16 DigitalRenderer::SawRectTable[0x100] = {
717     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
718     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
719     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
720     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
721     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
722     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
723     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
724     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
725     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
726     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
727     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
728     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
729     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
730     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
731     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
732     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
733     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
734     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
735     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
736     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
737     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
738     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
739     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
740     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE,
741     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
742     0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
743     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
744     0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC,
745     0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0,
746     0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC,
747     0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4,
748     0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF
749     };
750    
751     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
752     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
753     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
754     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
755     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
756     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
757     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
758     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
759     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
760     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
761     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
762     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
763     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
764     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
765     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
766     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
767     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
768     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
769     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
770     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
771     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
772     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
773     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
774     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
775     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
776     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
777     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
778     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
779     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
780     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
781     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
782     0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0,
783     0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC
784     };
785     #endif
786    
787     const uint32 DigitalRenderer::EGTable[16] = {
788     (SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32,
789     (SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95,
790     (SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220,
791     (SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313,
792     (SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977,
793     (SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126,
794     (SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720,
795     (SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251
796     };
797    
798     const uint8 DigitalRenderer::EGDRShift[256] = {
799     5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,
800     3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
801     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
802     2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,
803     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
804     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
805     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
806     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
807     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
808     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
809     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
810     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
811     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
812     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
813     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
814     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
815     };
816    
817     const int16 DigitalRenderer::SampleTab[16] = {
818     0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777,
819     0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff,
820     };
821    
822    
823     /*
824     * Constructor
825     */
826    
827     #if defined(__BEOS__) || defined(__riscos__)
828     DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64)
829     #else
830     DigitalRenderer::DigitalRenderer()
831     #endif
832     {
833     // Link voices together
834     voice[0].mod_by = &voice[2];
835     voice[1].mod_by = &voice[0];
836     voice[2].mod_by = &voice[1];
837     voice[0].mod_to = &voice[1];
838     voice[1].mod_to = &voice[2];
839     voice[2].mod_to = &voice[0];
840    
841     // Calculate triangle table
842     for (int i=0; i<0x1000; i++) {
843     TriTable[i] = (i << 4) | (i >> 8);
844     TriTable[0x1fff-i] = (i << 4) | (i >> 8);
845     }
846    
847     #ifdef PRECOMPUTE_RESONANCE
848     #ifdef USE_FIXPOINT_MATHS
849     // slow floating point doesn't matter much on startup!
850     for (int i=0; i<256; i++) {
851     resonanceLP[i] = FixNo(CALC_RESONANCE_LP(i));
852     resonanceHP[i] = FixNo(CALC_RESONANCE_HP(i));
853     }
854     // Pre-compute the quotient. No problem since int-part is small enough
855     sidquot = (int32)((((double)SID_FREQ)*65536) / SAMPLE_FREQ);
856     // compute lookup table for sin and cos
857     InitFixSinTab();
858     #else
859     for (int i=0; i<256; i++) {
860     resonanceLP[i] = CALC_RESONANCE_LP(i);
861     resonanceHP[i] = CALC_RESONANCE_HP(i);
862     }
863     #endif
864     #endif
865    
866     Reset();
867    
868     // System specific initialization
869     init_sound();
870     }
871    
872    
873     /*
874     * Reset emulation
875     */
876    
877     void DigitalRenderer::Reset(void)
878     {
879     volume = 0;
880     v3_mute = false;
881    
882     for (int v=0; v<3; v++) {
883     voice[v].wave = WAVE_NONE;
884     voice[v].eg_state = EG_IDLE;
885     voice[v].count = voice[v].add = 0;
886     voice[v].freq = voice[v].pw = 0;
887     voice[v].eg_level = voice[v].s_level = 0;
888     voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0];
889     voice[v].gate = voice[v].ring = voice[v].test = false;
890     voice[v].filter = voice[v].sync = false;
891     }
892    
893     f_type = FILT_NONE;
894     f_freq = f_res = 0;
895     #ifdef USE_FIXPOINT_MATHS
896     f_ampl = FixNo(1);
897     d1 = d2 = g1 = g2 = 0;
898     xn1 = xn2 = yn1 = yn2 = 0;
899     #else
900     f_ampl = 1.0;
901     d1 = d2 = g1 = g2 = 0.0;
902     xn1 = xn2 = yn1 = yn2 = 0.0;
903     #endif
904    
905     sample_in_ptr = 0;
906     memset(sample_buf, 0, SAMPLE_BUF_SIZE);
907     }
908    
909    
910     /*
911     * Write to register
912     */
913    
914     void DigitalRenderer::WriteRegister(uint16 adr, uint8 byte)
915     {
916     if (!ready)
917     return;
918    
919     int v = adr/7; // Voice number
920    
921     switch (adr) {
922     case 0:
923     case 7:
924     case 14:
925     voice[v].freq = (voice[v].freq & 0xff00) | byte;
926     #ifdef USE_FIXPOINT_MATHS
927     voice[v].add = sidquot.imul((int)voice[v].freq);
928     #else
929     voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
930     #endif
931     break;
932    
933     case 1:
934     case 8:
935     case 15:
936     voice[v].freq = (voice[v].freq & 0xff) | (byte << 8);
937     #ifdef USE_FIXPOINT_MATHS
938     voice[v].add = sidquot.imul((int)voice[v].freq);
939     #else
940     voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
941     #endif
942     break;
943    
944     case 2:
945     case 9:
946     case 16:
947     voice[v].pw = (voice[v].pw & 0x0f00) | byte;
948     break;
949    
950     case 3:
951     case 10:
952     case 17:
953     voice[v].pw = (voice[v].pw & 0xff) | ((byte & 0xf) << 8);
954     break;
955    
956     case 4:
957     case 11:
958     case 18:
959     voice[v].wave = (byte >> 4) & 0xf;
960     if ((byte & 1) != voice[v].gate)
961     if (byte & 1) // Gate turned on
962     voice[v].eg_state = EG_ATTACK;
963     else // Gate turned off
964     if (voice[v].eg_state != EG_IDLE)
965     voice[v].eg_state = EG_RELEASE;
966     voice[v].gate = byte & 1;
967     voice[v].mod_by->sync = byte & 2;
968     voice[v].ring = byte & 4;
969     if ((voice[v].test = byte & 8))
970     voice[v].count = 0;
971     break;
972    
973     case 5:
974     case 12:
975     case 19:
976     voice[v].a_add = EGTable[byte >> 4];
977     voice[v].d_sub = EGTable[byte & 0xf];
978     break;
979    
980     case 6:
981     case 13:
982     case 20:
983     voice[v].s_level = (byte >> 4) * 0x111111;
984     voice[v].r_sub = EGTable[byte & 0xf];
985     break;
986    
987     case 22:
988     if (byte != f_freq) {
989     f_freq = byte;
990     if (ThePrefs.SIDFilters)
991     calc_filter();
992     }
993     break;
994    
995     case 23:
996     voice[0].filter = byte & 1;
997     voice[1].filter = byte & 2;
998     voice[2].filter = byte & 4;
999     if ((byte >> 4) != f_res) {
1000     f_res = byte >> 4;
1001     if (ThePrefs.SIDFilters)
1002     calc_filter();
1003     }
1004     break;
1005    
1006     case 24:
1007     volume = byte & 0xf;
1008     v3_mute = byte & 0x80;
1009     if (((byte >> 4) & 7) != f_type) {
1010     f_type = (byte >> 4) & 7;
1011     #ifdef USE_FIXPOINT_MATHS
1012     xn1 = xn2 = yn1 = yn2 = 0;
1013     #else
1014     xn1 = xn2 = yn1 = yn2 = 0.0;
1015     #endif
1016     if (ThePrefs.SIDFilters)
1017     calc_filter();
1018     }
1019     break;
1020     }
1021     }
1022    
1023    
1024     /*
1025     * Preferences may have changed
1026     */
1027    
1028     void DigitalRenderer::NewPrefs(Prefs *prefs)
1029     {
1030     calc_filter();
1031     }
1032    
1033    
1034     /*
1035     * Calculate IIR filter coefficients
1036     */
1037    
1038     void DigitalRenderer::calc_filter(void)
1039     {
1040     #ifdef USE_FIXPOINT_MATHS
1041     FixPoint fr, arg;
1042    
1043     if (f_type == FILT_ALL)
1044     {
1045     d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = FixNo(1); return;
1046     }
1047     else if (f_type == FILT_NONE)
1048     {
1049     d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = 0; return;
1050     }
1051     #else
1052     float fr, arg;
1053    
1054     // Check for some trivial cases
1055     if (f_type == FILT_ALL) {
1056     d1 = 0.0; d2 = 0.0;
1057     g1 = 0.0; g2 = 0.0;
1058     f_ampl = 1.0;
1059     return;
1060     } else if (f_type == FILT_NONE) {
1061     d1 = 0.0; d2 = 0.0;
1062     g1 = 0.0; g2 = 0.0;
1063     f_ampl = 0.0;
1064     return;
1065     }
1066     #endif
1067    
1068     // Calculate resonance frequency
1069     if (f_type == FILT_LP || f_type == FILT_LPBP)
1070     #ifdef PRECOMPUTE_RESONANCE
1071     fr = resonanceLP[f_freq];
1072     #else
1073     fr = CALC_RESONANCE_LP(f_freq);
1074     #endif
1075     else
1076     #ifdef PRECOMPUTE_RESONANCE
1077     fr = resonanceHP[f_freq];
1078     #else
1079     fr = CALC_RESONANCE_HP(f_freq);
1080     #endif
1081    
1082     #ifdef USE_FIXPOINT_MATHS
1083     // explanations see below.
1084     arg = fr / (SAMPLE_FREQ >> 1);
1085     if (arg > FixNo(0.99)) {arg = FixNo(0.99);}
1086     if (arg < FixNo(0.01)) {arg = FixNo(0.01);}
1087    
1088     g2 = FixNo(0.55) + FixNo(1.2) * arg * (arg - 1) + FixNo(0.0133333333) * f_res;
1089     g1 = FixNo(-2) * g2.sqrt() * fixcos(arg);
1090    
1091     if (f_type == FILT_LPBP || f_type == FILT_HPBP) {g2 += FixNo(0.1);}
1092    
1093     if (g1.abs() >= g2 + 1)
1094     {
1095     if (g1 > 0) {g1 = g2 + FixNo(0.99);}
1096     else {g1 = -(g2 + FixNo(0.99));}
1097     }
1098    
1099     switch (f_type)
1100     {
1101     case FILT_LPBP:
1102     case FILT_LP:
1103     d1 = FixNo(2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 + g1 + g2); break;
1104     case FILT_HPBP:
1105     case FILT_HP:
1106     d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break;
1107     case FILT_BP:
1108     d1 = 0; d2 = FixNo(-1);
1109     f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
1110     break;
1111     case FILT_NOTCH:
1112     d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1);
1113     f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
1114     break;
1115     default: break;
1116     }
1117    
1118     #else
1119    
1120     // Limit to <1/2 sample frequency, avoid div by 0 in case FILT_BP below
1121     arg = fr / (float)(SAMPLE_FREQ >> 1);
1122     if (arg > 0.99)
1123     arg = 0.99;
1124     if (arg < 0.01)
1125     arg = 0.01;
1126    
1127     // Calculate poles (resonance frequency and resonance)
1128     g2 = 0.55 + 1.2 * arg * arg - 1.2 * arg + (float)f_res * 0.0133333333;
1129     g1 = -2.0 * sqrt(g2) * cos(M_PI * arg);
1130    
1131     // Increase resonance if LP/HP combined with BP
1132     if (f_type == FILT_LPBP || f_type == FILT_HPBP)
1133     g2 += 0.1;
1134    
1135     // Stabilize filter
1136     if (fabs(g1) >= g2 + 1.0)
1137     if (g1 > 0.0)
1138     g1 = g2 + 0.99;
1139     else
1140     g1 = -(g2 + 0.99);
1141    
1142     // Calculate roots (filter characteristic) and input attenuation
1143     switch (f_type) {
1144    
1145     case FILT_LPBP:
1146     case FILT_LP:
1147     d1 = 2.0; d2 = 1.0;
1148     f_ampl = 0.25 * (1.0 + g1 + g2);
1149     break;
1150    
1151     case FILT_HPBP:
1152     case FILT_HP:
1153     d1 = -2.0; d2 = 1.0;
1154     f_ampl = 0.25 * (1.0 - g1 + g2);
1155     break;
1156    
1157     case FILT_BP:
1158     d1 = 0.0; d2 = -1.0;
1159     f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / sin(M_PI * arg);
1160     break;
1161    
1162     case FILT_NOTCH:
1163     d1 = -2.0 * cos(M_PI * arg); d2 = 1.0;
1164     f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / (sin(M_PI * arg));
1165     break;
1166    
1167     default:
1168     break;
1169     }
1170     #endif
1171     }
1172    
1173    
1174     /*
1175     * Fill one audio buffer with calculated SID sound
1176     */
1177    
1178     #ifdef __riscos__
1179     void DigitalRenderer::calc_buffer(uint8 *buf, long count)
1180     #else
1181     void DigitalRenderer::calc_buffer(int16 *buf, long count)
1182     #endif
1183     {
1184     // Get filter coefficients, so the emulator won't change
1185     // them in the middle of our calculations
1186     #ifdef USE_FIXPOINT_MATHS
1187     FixPoint cf_ampl = f_ampl;
1188     FixPoint cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
1189     #else
1190     float cf_ampl = f_ampl;
1191     float cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
1192     #endif
1193    
1194     #ifdef __riscos__
1195     uint8 *LinToLog, *LogScale;
1196     #endif
1197    
1198     // Index in sample_buf for reading, 16.16 fixed
1199     uint32 sample_count = (sample_in_ptr + SAMPLE_BUF_SIZE/2) << 16;
1200    
1201     #ifdef __riscos__ // on RISC OS we have 8 bit logarithmic sound
1202     DigitalRenderer_GetTables(&LinToLog, &LogScale); // get translation tables
1203     #else
1204     #ifdef __BEOS__
1205     count >>= 2; // 16 bit stereo output, count is in bytes
1206     #else
1207     count >>= 1; // 16 bit mono output, count is in bytes
1208     #endif
1209     #endif
1210     while (count--) {
1211     int32 sum_output;
1212     int32 sum_output_filter = 0;
1213    
1214     // Get current master volume from sample buffer,
1215     // calculate sampled voice
1216     uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE];
1217     sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ;
1218     sum_output = SampleTab[master_volume] << 8;
1219    
1220     // Loop for all three voices
1221     for (int j=0; j<3; j++) {
1222     DRVoice *v = &voice[j];
1223    
1224     // Envelope generators
1225     uint16 envelope;
1226    
1227     switch (v->eg_state) {
1228     case EG_ATTACK:
1229     v->eg_level += v->a_add;
1230     if (v->eg_level > 0xffffff) {
1231     v->eg_level = 0xffffff;
1232     v->eg_state = EG_DECAY;
1233     }
1234     break;
1235     case EG_DECAY:
1236     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1237     v->eg_level = v->s_level;
1238     else {
1239     v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16];
1240     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1241     v->eg_level = v->s_level;
1242     }
1243     break;
1244     case EG_RELEASE:
1245     v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16];
1246     if (v->eg_level > 0xffffff) {
1247     v->eg_level = 0;
1248     v->eg_state = EG_IDLE;
1249     }
1250     break;
1251     case EG_IDLE:
1252     v->eg_level = 0;
1253     break;
1254     }
1255     envelope = (v->eg_level * master_volume) >> 20;
1256    
1257     // Waveform generator
1258     uint16 output;
1259    
1260     if (!v->test)
1261     v->count += v->add;
1262    
1263     if (v->sync && (v->count > 0x1000000))
1264     v->mod_to->count = 0;
1265    
1266     v->count &= 0xffffff;
1267    
1268     switch (v->wave) {
1269     case WAVE_TRI:
1270     if (v->ring)
1271     output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11];
1272     else
1273     output = TriTable[v->count >> 11];
1274     break;
1275     case WAVE_SAW:
1276     output = v->count >> 8;
1277     break;
1278     case WAVE_RECT:
1279     if (v->count > (uint32)(v->pw << 12))
1280     output = 0xffff;
1281     else
1282     output = 0;
1283     break;
1284     case WAVE_TRISAW:
1285     output = TriSawTable[v->count >> 16];
1286     break;
1287     case WAVE_TRIRECT:
1288     if (v->count > (uint32)(v->pw << 12))
1289     output = TriRectTable[v->count >> 16];
1290     else
1291     output = 0;
1292     break;
1293     case WAVE_SAWRECT:
1294     if (v->count > (uint32)(v->pw << 12))
1295     output = SawRectTable[v->count >> 16];
1296     else
1297     output = 0;
1298     break;
1299     case WAVE_TRISAWRECT:
1300     if (v->count > (uint32)(v->pw << 12))
1301     output = TriSawRectTable[v->count >> 16];
1302     else
1303     output = 0;
1304     break;
1305     case WAVE_NOISE:
1306     if (v->count > 0x100000) {
1307     output = v->noise = sid_random() << 8;
1308     v->count &= 0xfffff;
1309     } else
1310     output = v->noise;
1311     break;
1312     default:
1313     output = 0x8000;
1314     break;
1315     }
1316     if (v->filter)
1317     sum_output_filter += (int16)(output ^ 0x8000) * envelope;
1318     else
1319     sum_output += (int16)(output ^ 0x8000) * envelope;
1320     }
1321    
1322     // Filter
1323     if (ThePrefs.SIDFilters) {
1324     #ifdef USE_FIXPOINT_MATHS
1325     int32 xn = cf_ampl.imul(sum_output_filter);
1326     int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2);
1327     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1328     sum_output_filter = yn;
1329     #else
1330     float xn = (float)sum_output_filter * cf_ampl;
1331     float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2;
1332     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1333     sum_output_filter = (int32)yn;
1334     #endif
1335     }
1336    
1337     // Write to buffer
1338     #ifdef __BEOS__
1339     int16 audio_data = (sum_output + sum_output_filter) >> 10;
1340     int val = *buf + audio_data;
1341     if (val > 32767)
1342     val = 32767;
1343     if (val < -32768)
1344     val = -32768;
1345     *buf++ = val;
1346     val = *buf + audio_data;
1347     if (val > 32767)
1348     val = 32767;
1349     if (val < -32768)
1350     val = -32768;
1351     *buf++ = val;
1352     #elif defined(__riscos__) // lookup in 8k (13bit) translation table
1353     *buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff];
1354     #else
1355     *buf++ = (sum_output + sum_output_filter) >> 10;
1356     #endif
1357     }
1358     }
1359    
1360    
1361     // Manufacturer independent sound is still just a dream...
1362     #if defined(__BEOS__)
1363     #include "SID_Be.h"
1364    
1365     #elif defined(AMIGA)
1366     #include "SID_Amiga.h"
1367    
1368     #elif defined(__linux__)
1369     #include "SID_linux.h"
1370    
1371     #elif defined(SUN)
1372     #include "SID_sun.h"
1373    
1374     #elif defined(__hpux)
1375     #include "SID_hp.h"
1376    
1377     #elif defined(__mac__)
1378     #include "SID_mac.h"
1379    
1380     #elif defined(WIN32)
1381     #include "SID_WIN32.h"
1382    
1383     #elif defined(__riscos__)
1384     #include "SID_Acorn.h"
1385    
1386     #else // No sound
1387     void DigitalRenderer::init_sound(void) {ready = false;}
1388     DigitalRenderer::~DigitalRenderer() {}
1389     void DigitalRenderer::EmulateLine(void) {}
1390     void DigitalRenderer::Pause(void) {}
1391     void DigitalRenderer::Resume(void) {}
1392     #endif
1393    
1394    
1395     /*
1396     * Open/close the renderer, according to old and new prefs
1397     */
1398    
1399     void MOS6581::open_close_renderer(int old_type, int new_type)
1400     {
1401     if (old_type == new_type)
1402     return;
1403    
1404     // Delete the old renderer
1405     delete the_renderer;
1406    
1407     // Create new renderer
1408     if (new_type == SIDTYPE_DIGITAL)
1409     #if defined(__BEOS__) || defined(__riscos__)
1410     the_renderer = new DigitalRenderer(the_c64);
1411     #else
1412     the_renderer = new DigitalRenderer();
1413     #endif
1414     #ifdef AMIGA
1415     else if (new_type == SIDTYPE_SIDCARD)
1416     the_renderer = new SIDCardRenderer();
1417     #endif
1418     else
1419     the_renderer = NULL;
1420    
1421     // Stuff the current register values into the new renderer
1422     if (the_renderer != NULL)
1423     for (int i=0; i<25; i++)
1424     the_renderer->WriteRegister(i, regs[i]);
1425     }