ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.6
Committed: 2004-01-12T15:13:20Z (20 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.5: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * SID.cpp - 6581 emulation
3     *
4 cebix 1.6 * Frodo (C) 1994-1997,2002-2004 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     #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    
383     static uint16 TriTable[0x1000*2]; // Tables for certain waveforms
384     static const uint16 TriSawTable[0x100];
385     static const uint16 TriRectTable[0x100];
386     static const uint16 SawRectTable[0x100];
387     static const uint16 TriSawRectTable[0x100];
388     static const uint32 EGTable[16]; // Increment/decrement values for all A/D/R settings
389     static const uint8 EGDRShift[256]; // For exponential approximation of D/R
390     static const int16 SampleTab[16]; // Table for sampled voice
391    
392     DRVoice voice[3]; // Data for 3 voices
393    
394     uint8 f_type; // Filter type
395     uint8 f_freq; // SID filter frequency (upper 8 bits)
396     uint8 f_res; // Filter resonance (0..15)
397     #ifdef USE_FIXPOINT_MATHS
398     FixPoint f_ampl;
399     FixPoint d1, d2, g1, g2;
400     int32 xn1, xn2, yn1, yn2; // can become very large
401     FixPoint sidquot;
402     #ifdef PRECOMPUTE_RESONANCE
403     FixPoint resonanceLP[256];
404     FixPoint resonanceHP[256];
405     #endif
406     #else
407     float f_ampl; // IIR filter input attenuation
408     float d1, d2, g1, g2; // IIR filter coefficients
409     float xn1, xn2, yn1, yn2; // IIR filter previous input/output signal
410     #ifdef PRECOMPUTE_RESONANCE
411     float resonanceLP[256]; // shortcut for calc_filter
412     float resonanceHP[256];
413     #endif
414     #endif
415    
416     uint8 sample_buf[SAMPLE_BUF_SIZE]; // Buffer for sampled voice
417     int sample_in_ptr; // Index in sample_buf for writing
418    
419     #ifdef __BEOS__
420 cebix 1.4 static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format);
421 cebix 1.1 C64 *the_c64; // Pointer to C64 object
422 cebix 1.4 BSoundPlayer *the_player; // Pointer to sound player
423     bool player_stopped; // Flag: player stopped
424 cebix 1.1 #endif
425    
426     #ifdef AMIGA
427     static void sub_invoc(void); // Sound sub-process
428     void sub_func(void);
429     struct Process *sound_process;
430     int quit_sig, pause_sig,
431     resume_sig, ahi_sig; // Sub-process signals
432     struct Task *main_task; // Main task
433     int main_sig; // Main task signals
434     static ULONG sound_func(void); // AHI callback
435     struct MsgPort *ahi_port; // Port and IORequest for AHI
436     struct AHIRequest *ahi_io;
437     struct AHIAudioCtrl *ahi_ctrl; // AHI control structure
438     struct AHISampleInfo sample[2]; // SampleInfos for double buffering
439     struct Hook sf_hook; // Hook for callback function
440     int play_buf; // Number of buffer currently playing
441     #endif
442    
443     #ifdef __linux__
444     int devfd, sndbufsize, buffer_rate;
445     int16 *sound_buffer;
446     #endif
447    
448     #ifdef SUN
449     int fd;
450     audio_info status;
451     uint_t sent_samples,delta_samples;
452 cebix 1.3 int16 *sound_calc_buf;
453 cebix 1.1 #endif
454    
455     #ifdef __hpux
456     int fd;
457     audio_status status;
458 cebix 1.3 int16 *sound_calc_buf;
459 cebix 1.1 int linecnt;
460     #endif
461    
462     #ifdef __mac__
463     SndChannelPtr chan1;
464     SndDoubleBufferHeader myDblHeader;
465     SndDoubleBufferPtr sampleBuffer1, sampleBuffer2;
466     SCStatus myStatus;
467     short sndbufsize;
468     OSErr err;
469    
470     static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
471     #endif
472    
473     #ifdef WIN32
474     public:
475     void VBlank(void);
476    
477     private:
478     void StartPlayer(void);
479     void StopPlayer(void);
480    
481     BOOL direct_sound;
482     DigitalPlayer *ThePlayer;
483     SWORD *sound_buffer;
484     int to_output;
485     int sb_pos;
486     int divisor;
487     int *lead;
488     int lead_pos;
489     #endif
490    
491     #ifdef __riscos__
492     int linecnt, sndbufsize;
493     uint8 *sound_buffer;
494     C64 *the_c64;
495     #endif
496     };
497    
498     // Static data members
499     uint16 DigitalRenderer::TriTable[0x1000*2];
500    
501     #ifndef EMUL_MOS8580
502     // Sampled from a 6581R4
503     const uint16 DigitalRenderer::TriSawTable[0x100] = {
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, 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, 0x0808,
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, 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, 0x1010, 0x3C3C,
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, 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, 0x0808,
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, 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, 0x1010, 0x3C3C
536     };
537    
538     const uint16 DigitalRenderer::TriRectTable[0x100] = {
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, 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, 0x8080,
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, 0x8080, 0xC0C0,
554     0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC,
555     0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080,
556     0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000,
557     0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
558     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
559     0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
560     0x8080, 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     0x7E7E, 0x4040, 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     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     };
572    
573     const uint16 DigitalRenderer::SawRectTable[0x100] = {
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, 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, 0x7878,
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, 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, 0x7878
606     };
607    
608     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
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     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     };
642     #else
643     // Sampled from an 8580R5
644     const uint16 DigitalRenderer::TriSawTable[0x100] = {
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, 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, 0x0808,
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, 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, 0x1818, 0x3C3C,
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, 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, 0x1C1C,
669     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
670     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
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, 0x8080, 0x0000, 0x8080, 0x8080,
675     0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0,
676     0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE
677     };
678    
679     const uint16 DigitalRenderer::TriRectTable[0x100] = {
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     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     0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0,
697     0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0,
698     0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080,
699     0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000,
700     0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000,
701     0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
702     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
703     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
704     0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 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     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     };
713    
714     const uint16 DigitalRenderer::SawRectTable[0x100] = {
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, 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, 0x8080,
737     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
738     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE,
739     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
740     0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
741     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
742     0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC,
743     0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0,
744     0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC,
745     0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4,
746     0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF
747     };
748    
749     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
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, 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, 0x8080, 0x8080,
780     0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0,
781     0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC
782     };
783     #endif
784    
785     const uint32 DigitalRenderer::EGTable[16] = {
786     (SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32,
787     (SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95,
788     (SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220,
789     (SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313,
790     (SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977,
791     (SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126,
792     (SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720,
793     (SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251
794     };
795    
796     const uint8 DigitalRenderer::EGDRShift[256] = {
797     5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,
798     3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
799     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
800     2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,
801     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
802     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
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     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     };
814    
815     const int16 DigitalRenderer::SampleTab[16] = {
816     0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777,
817     0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff,
818     };
819    
820    
821     /*
822     * Constructor
823     */
824    
825     #if defined(__BEOS__) || defined(__riscos__)
826     DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64)
827     #else
828     DigitalRenderer::DigitalRenderer()
829     #endif
830     {
831     // Link voices together
832     voice[0].mod_by = &voice[2];
833     voice[1].mod_by = &voice[0];
834     voice[2].mod_by = &voice[1];
835     voice[0].mod_to = &voice[1];
836     voice[1].mod_to = &voice[2];
837     voice[2].mod_to = &voice[0];
838    
839     // Calculate triangle table
840     for (int i=0; i<0x1000; i++) {
841     TriTable[i] = (i << 4) | (i >> 8);
842     TriTable[0x1fff-i] = (i << 4) | (i >> 8);
843     }
844    
845     #ifdef PRECOMPUTE_RESONANCE
846     #ifdef USE_FIXPOINT_MATHS
847     // slow floating point doesn't matter much on startup!
848     for (int i=0; i<256; i++) {
849     resonanceLP[i] = FixNo(CALC_RESONANCE_LP(i));
850     resonanceHP[i] = FixNo(CALC_RESONANCE_HP(i));
851     }
852     // Pre-compute the quotient. No problem since int-part is small enough
853     sidquot = (int32)((((double)SID_FREQ)*65536) / SAMPLE_FREQ);
854     // compute lookup table for sin and cos
855     InitFixSinTab();
856     #else
857     for (int i=0; i<256; i++) {
858     resonanceLP[i] = CALC_RESONANCE_LP(i);
859     resonanceHP[i] = CALC_RESONANCE_HP(i);
860     }
861     #endif
862     #endif
863    
864     Reset();
865    
866     // System specific initialization
867     init_sound();
868     }
869    
870    
871     /*
872     * Reset emulation
873     */
874    
875     void DigitalRenderer::Reset(void)
876     {
877     volume = 0;
878    
879     for (int v=0; v<3; v++) {
880     voice[v].wave = WAVE_NONE;
881     voice[v].eg_state = EG_IDLE;
882     voice[v].count = voice[v].add = 0;
883     voice[v].freq = voice[v].pw = 0;
884     voice[v].eg_level = voice[v].s_level = 0;
885     voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0];
886     voice[v].gate = voice[v].ring = voice[v].test = false;
887 cebix 1.3 voice[v].filter = voice[v].sync = voice[v].mute = false;
888 cebix 1.1 }
889    
890     f_type = FILT_NONE;
891     f_freq = f_res = 0;
892     #ifdef USE_FIXPOINT_MATHS
893     f_ampl = FixNo(1);
894     d1 = d2 = g1 = g2 = 0;
895     xn1 = xn2 = yn1 = yn2 = 0;
896     #else
897     f_ampl = 1.0;
898     d1 = d2 = g1 = g2 = 0.0;
899     xn1 = xn2 = yn1 = yn2 = 0.0;
900     #endif
901    
902     sample_in_ptr = 0;
903     memset(sample_buf, 0, SAMPLE_BUF_SIZE);
904     }
905    
906    
907     /*
908     * Write to register
909     */
910    
911     void DigitalRenderer::WriteRegister(uint16 adr, uint8 byte)
912     {
913     if (!ready)
914     return;
915    
916     int v = adr/7; // Voice number
917    
918     switch (adr) {
919     case 0:
920     case 7:
921     case 14:
922     voice[v].freq = (voice[v].freq & 0xff00) | byte;
923     #ifdef USE_FIXPOINT_MATHS
924     voice[v].add = sidquot.imul((int)voice[v].freq);
925     #else
926     voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
927     #endif
928     break;
929    
930     case 1:
931     case 8:
932     case 15:
933     voice[v].freq = (voice[v].freq & 0xff) | (byte << 8);
934     #ifdef USE_FIXPOINT_MATHS
935     voice[v].add = sidquot.imul((int)voice[v].freq);
936     #else
937     voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ);
938     #endif
939     break;
940    
941     case 2:
942     case 9:
943     case 16:
944     voice[v].pw = (voice[v].pw & 0x0f00) | byte;
945     break;
946    
947     case 3:
948     case 10:
949     case 17:
950     voice[v].pw = (voice[v].pw & 0xff) | ((byte & 0xf) << 8);
951     break;
952    
953     case 4:
954     case 11:
955     case 18:
956     voice[v].wave = (byte >> 4) & 0xf;
957     if ((byte & 1) != voice[v].gate)
958     if (byte & 1) // Gate turned on
959     voice[v].eg_state = EG_ATTACK;
960     else // Gate turned off
961     if (voice[v].eg_state != EG_IDLE)
962     voice[v].eg_state = EG_RELEASE;
963     voice[v].gate = byte & 1;
964     voice[v].mod_by->sync = byte & 2;
965     voice[v].ring = byte & 4;
966 cebix 1.3 if ((voice[v].test = byte & 8) != 0)
967 cebix 1.1 voice[v].count = 0;
968     break;
969    
970     case 5:
971     case 12:
972     case 19:
973     voice[v].a_add = EGTable[byte >> 4];
974     voice[v].d_sub = EGTable[byte & 0xf];
975     break;
976    
977     case 6:
978     case 13:
979     case 20:
980     voice[v].s_level = (byte >> 4) * 0x111111;
981     voice[v].r_sub = EGTable[byte & 0xf];
982     break;
983    
984     case 22:
985     if (byte != f_freq) {
986     f_freq = byte;
987     if (ThePrefs.SIDFilters)
988     calc_filter();
989     }
990     break;
991    
992     case 23:
993     voice[0].filter = byte & 1;
994     voice[1].filter = byte & 2;
995     voice[2].filter = byte & 4;
996     if ((byte >> 4) != f_res) {
997     f_res = byte >> 4;
998     if (ThePrefs.SIDFilters)
999     calc_filter();
1000     }
1001     break;
1002    
1003     case 24:
1004     volume = byte & 0xf;
1005 cebix 1.3 voice[2].mute = byte & 0x80;
1006 cebix 1.1 if (((byte >> 4) & 7) != f_type) {
1007     f_type = (byte >> 4) & 7;
1008     #ifdef USE_FIXPOINT_MATHS
1009     xn1 = xn2 = yn1 = yn2 = 0;
1010     #else
1011     xn1 = xn2 = yn1 = yn2 = 0.0;
1012     #endif
1013     if (ThePrefs.SIDFilters)
1014     calc_filter();
1015     }
1016     break;
1017     }
1018     }
1019    
1020    
1021     /*
1022     * Preferences may have changed
1023     */
1024    
1025     void DigitalRenderer::NewPrefs(Prefs *prefs)
1026     {
1027     calc_filter();
1028     }
1029    
1030    
1031     /*
1032     * Calculate IIR filter coefficients
1033     */
1034    
1035     void DigitalRenderer::calc_filter(void)
1036     {
1037     #ifdef USE_FIXPOINT_MATHS
1038     FixPoint fr, arg;
1039    
1040     if (f_type == FILT_ALL)
1041     {
1042     d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = FixNo(1); return;
1043     }
1044     else if (f_type == FILT_NONE)
1045     {
1046     d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = 0; return;
1047     }
1048     #else
1049     float fr, arg;
1050    
1051     // Check for some trivial cases
1052     if (f_type == FILT_ALL) {
1053     d1 = 0.0; d2 = 0.0;
1054     g1 = 0.0; g2 = 0.0;
1055     f_ampl = 1.0;
1056     return;
1057     } else if (f_type == FILT_NONE) {
1058     d1 = 0.0; d2 = 0.0;
1059     g1 = 0.0; g2 = 0.0;
1060     f_ampl = 0.0;
1061     return;
1062     }
1063     #endif
1064    
1065     // Calculate resonance frequency
1066     if (f_type == FILT_LP || f_type == FILT_LPBP)
1067     #ifdef PRECOMPUTE_RESONANCE
1068     fr = resonanceLP[f_freq];
1069     #else
1070     fr = CALC_RESONANCE_LP(f_freq);
1071     #endif
1072     else
1073     #ifdef PRECOMPUTE_RESONANCE
1074     fr = resonanceHP[f_freq];
1075     #else
1076     fr = CALC_RESONANCE_HP(f_freq);
1077     #endif
1078    
1079     #ifdef USE_FIXPOINT_MATHS
1080     // explanations see below.
1081     arg = fr / (SAMPLE_FREQ >> 1);
1082     if (arg > FixNo(0.99)) {arg = FixNo(0.99);}
1083     if (arg < FixNo(0.01)) {arg = FixNo(0.01);}
1084    
1085     g2 = FixNo(0.55) + FixNo(1.2) * arg * (arg - 1) + FixNo(0.0133333333) * f_res;
1086     g1 = FixNo(-2) * g2.sqrt() * fixcos(arg);
1087    
1088     if (f_type == FILT_LPBP || f_type == FILT_HPBP) {g2 += FixNo(0.1);}
1089    
1090     if (g1.abs() >= g2 + 1)
1091     {
1092     if (g1 > 0) {g1 = g2 + FixNo(0.99);}
1093     else {g1 = -(g2 + FixNo(0.99));}
1094     }
1095    
1096     switch (f_type)
1097     {
1098     case FILT_LPBP:
1099     case FILT_LP:
1100     d1 = FixNo(2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 + g1 + g2); break;
1101     case FILT_HPBP:
1102     case FILT_HP:
1103     d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break;
1104     case FILT_BP:
1105     d1 = 0; d2 = FixNo(-1);
1106     f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
1107     break;
1108     case FILT_NOTCH:
1109     d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1);
1110     f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg);
1111     break;
1112     default: break;
1113     }
1114    
1115     #else
1116    
1117     // Limit to <1/2 sample frequency, avoid div by 0 in case FILT_BP below
1118     arg = fr / (float)(SAMPLE_FREQ >> 1);
1119     if (arg > 0.99)
1120     arg = 0.99;
1121     if (arg < 0.01)
1122     arg = 0.01;
1123    
1124     // Calculate poles (resonance frequency and resonance)
1125     g2 = 0.55 + 1.2 * arg * arg - 1.2 * arg + (float)f_res * 0.0133333333;
1126     g1 = -2.0 * sqrt(g2) * cos(M_PI * arg);
1127    
1128     // Increase resonance if LP/HP combined with BP
1129     if (f_type == FILT_LPBP || f_type == FILT_HPBP)
1130     g2 += 0.1;
1131    
1132     // Stabilize filter
1133     if (fabs(g1) >= g2 + 1.0)
1134     if (g1 > 0.0)
1135     g1 = g2 + 0.99;
1136     else
1137     g1 = -(g2 + 0.99);
1138    
1139     // Calculate roots (filter characteristic) and input attenuation
1140     switch (f_type) {
1141    
1142     case FILT_LPBP:
1143     case FILT_LP:
1144     d1 = 2.0; d2 = 1.0;
1145     f_ampl = 0.25 * (1.0 + g1 + g2);
1146     break;
1147    
1148     case FILT_HPBP:
1149     case FILT_HP:
1150     d1 = -2.0; d2 = 1.0;
1151     f_ampl = 0.25 * (1.0 - g1 + g2);
1152     break;
1153    
1154     case FILT_BP:
1155     d1 = 0.0; d2 = -1.0;
1156     f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / sin(M_PI * arg);
1157     break;
1158    
1159     case FILT_NOTCH:
1160     d1 = -2.0 * cos(M_PI * arg); d2 = 1.0;
1161     f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / (sin(M_PI * arg));
1162     break;
1163    
1164     default:
1165     break;
1166     }
1167     #endif
1168     }
1169    
1170    
1171     /*
1172     * Fill one audio buffer with calculated SID sound
1173     */
1174    
1175     #ifdef __riscos__
1176     void DigitalRenderer::calc_buffer(uint8 *buf, long count)
1177     #else
1178     void DigitalRenderer::calc_buffer(int16 *buf, long count)
1179     #endif
1180     {
1181     // Get filter coefficients, so the emulator won't change
1182     // them in the middle of our calculations
1183     #ifdef USE_FIXPOINT_MATHS
1184     FixPoint cf_ampl = f_ampl;
1185     FixPoint cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
1186     #else
1187     float cf_ampl = f_ampl;
1188     float cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2;
1189     #endif
1190    
1191     #ifdef __riscos__
1192     uint8 *LinToLog, *LogScale;
1193     #endif
1194    
1195     // Index in sample_buf for reading, 16.16 fixed
1196     uint32 sample_count = (sample_in_ptr + SAMPLE_BUF_SIZE/2) << 16;
1197    
1198     #ifdef __riscos__ // on RISC OS we have 8 bit logarithmic sound
1199     DigitalRenderer_GetTables(&LinToLog, &LogScale); // get translation tables
1200     #else
1201     count >>= 1; // 16 bit mono output, count is in bytes
1202     #endif
1203     while (count--) {
1204     int32 sum_output;
1205     int32 sum_output_filter = 0;
1206    
1207     // Get current master volume from sample buffer,
1208     // calculate sampled voice
1209     uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE];
1210     sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ;
1211     sum_output = SampleTab[master_volume] << 8;
1212    
1213     // Loop for all three voices
1214     for (int j=0; j<3; j++) {
1215     DRVoice *v = &voice[j];
1216    
1217     // Envelope generators
1218     uint16 envelope;
1219    
1220     switch (v->eg_state) {
1221     case EG_ATTACK:
1222     v->eg_level += v->a_add;
1223     if (v->eg_level > 0xffffff) {
1224     v->eg_level = 0xffffff;
1225     v->eg_state = EG_DECAY;
1226     }
1227     break;
1228     case EG_DECAY:
1229     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1230     v->eg_level = v->s_level;
1231     else {
1232     v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16];
1233     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1234     v->eg_level = v->s_level;
1235     }
1236     break;
1237     case EG_RELEASE:
1238     v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16];
1239     if (v->eg_level > 0xffffff) {
1240     v->eg_level = 0;
1241     v->eg_state = EG_IDLE;
1242     }
1243     break;
1244     case EG_IDLE:
1245     v->eg_level = 0;
1246     break;
1247     }
1248     envelope = (v->eg_level * master_volume) >> 20;
1249    
1250     // Waveform generator
1251 cebix 1.3 if (v->mute)
1252     continue;
1253 cebix 1.1 uint16 output;
1254    
1255     if (!v->test)
1256     v->count += v->add;
1257    
1258     if (v->sync && (v->count > 0x1000000))
1259     v->mod_to->count = 0;
1260    
1261     v->count &= 0xffffff;
1262    
1263     switch (v->wave) {
1264     case WAVE_TRI:
1265     if (v->ring)
1266     output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11];
1267     else
1268     output = TriTable[v->count >> 11];
1269     break;
1270     case WAVE_SAW:
1271     output = v->count >> 8;
1272     break;
1273     case WAVE_RECT:
1274     if (v->count > (uint32)(v->pw << 12))
1275     output = 0xffff;
1276     else
1277     output = 0;
1278     break;
1279     case WAVE_TRISAW:
1280     output = TriSawTable[v->count >> 16];
1281     break;
1282     case WAVE_TRIRECT:
1283     if (v->count > (uint32)(v->pw << 12))
1284     output = TriRectTable[v->count >> 16];
1285     else
1286     output = 0;
1287     break;
1288     case WAVE_SAWRECT:
1289     if (v->count > (uint32)(v->pw << 12))
1290     output = SawRectTable[v->count >> 16];
1291     else
1292     output = 0;
1293     break;
1294     case WAVE_TRISAWRECT:
1295     if (v->count > (uint32)(v->pw << 12))
1296     output = TriSawRectTable[v->count >> 16];
1297     else
1298     output = 0;
1299     break;
1300     case WAVE_NOISE:
1301     if (v->count > 0x100000) {
1302     output = v->noise = sid_random() << 8;
1303     v->count &= 0xfffff;
1304     } else
1305     output = v->noise;
1306     break;
1307     default:
1308     output = 0x8000;
1309     break;
1310     }
1311     if (v->filter)
1312     sum_output_filter += (int16)(output ^ 0x8000) * envelope;
1313     else
1314     sum_output += (int16)(output ^ 0x8000) * envelope;
1315     }
1316    
1317     // Filter
1318     if (ThePrefs.SIDFilters) {
1319     #ifdef USE_FIXPOINT_MATHS
1320     int32 xn = cf_ampl.imul(sum_output_filter);
1321     int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2);
1322     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1323     sum_output_filter = yn;
1324     #else
1325     float xn = (float)sum_output_filter * cf_ampl;
1326     float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2;
1327     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1328     sum_output_filter = (int32)yn;
1329     #endif
1330     }
1331    
1332     // Write to buffer
1333 cebix 1.4 #if defined(__riscos__) // lookup in 8k (13bit) translation table
1334 cebix 1.1 *buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff];
1335     #else
1336     *buf++ = (sum_output + sum_output_filter) >> 10;
1337     #endif
1338     }
1339     }
1340    
1341    
1342     // Manufacturer independent sound is still just a dream...
1343     #if defined(__BEOS__)
1344     #include "SID_Be.h"
1345    
1346     #elif defined(AMIGA)
1347     #include "SID_Amiga.h"
1348    
1349     #elif defined(__linux__)
1350     #include "SID_linux.h"
1351    
1352     #elif defined(SUN)
1353     #include "SID_sun.h"
1354    
1355     #elif defined(__hpux)
1356     #include "SID_hp.h"
1357    
1358     #elif defined(__mac__)
1359     #include "SID_mac.h"
1360    
1361     #elif defined(WIN32)
1362     #include "SID_WIN32.h"
1363    
1364     #elif defined(__riscos__)
1365     #include "SID_Acorn.h"
1366    
1367     #else // No sound
1368     void DigitalRenderer::init_sound(void) {ready = false;}
1369     DigitalRenderer::~DigitalRenderer() {}
1370     void DigitalRenderer::EmulateLine(void) {}
1371     void DigitalRenderer::Pause(void) {}
1372     void DigitalRenderer::Resume(void) {}
1373     #endif
1374    
1375    
1376     /*
1377     * Open/close the renderer, according to old and new prefs
1378     */
1379    
1380     void MOS6581::open_close_renderer(int old_type, int new_type)
1381     {
1382     if (old_type == new_type)
1383     return;
1384    
1385     // Delete the old renderer
1386     delete the_renderer;
1387    
1388     // Create new renderer
1389     if (new_type == SIDTYPE_DIGITAL)
1390     #if defined(__BEOS__) || defined(__riscos__)
1391     the_renderer = new DigitalRenderer(the_c64);
1392     #else
1393     the_renderer = new DigitalRenderer();
1394     #endif
1395     #ifdef AMIGA
1396     else if (new_type == SIDTYPE_SIDCARD)
1397     the_renderer = new SIDCardRenderer();
1398     #endif
1399 cebix 1.5 #ifdef __linux__
1400     else if (new_type == SIDTYPE_SIDCARD)
1401     the_renderer = new CatweaselRenderer();
1402     #endif
1403 cebix 1.1 else
1404     the_renderer = NULL;
1405    
1406     // Stuff the current register values into the new renderer
1407     if (the_renderer != NULL)
1408     for (int i=0; i<25; i++)
1409     the_renderer->WriteRegister(i, regs[i]);
1410     }