ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.9
Committed: 2010-04-22T07:58:53Z (14 years ago) by cebix
Branch: MAIN
Changes since 1.8: +8 -19 lines
Log Message:
streamlining

File Contents

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