ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.10
Committed: 2010-04-22T09:09:28Z (14 years ago) by cebix
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +21 -6 lines
Log Message:
use SDL for sound

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 cebix 1.10
441     #ifdef HAVE_SDL
442     static void buffer_proc(void *cookie, uint8 *buffer, int size);
443     #else
444    
445     # ifdef __linux__
446 cebix 1.1 int devfd, sndbufsize, buffer_rate;
447     int16 *sound_buffer;
448 cebix 1.10 # endif
449 cebix 1.1
450 cebix 1.10 # ifdef SUN
451 cebix 1.1 int fd;
452     audio_info status;
453     uint_t sent_samples,delta_samples;
454 cebix 1.3 int16 *sound_calc_buf;
455 cebix 1.10 # endif
456 cebix 1.1
457 cebix 1.10 # ifdef __hpux
458 cebix 1.1 int fd;
459     audio_status status;
460 cebix 1.3 int16 *sound_calc_buf;
461 cebix 1.1 int linecnt;
462 cebix 1.10 # endif
463    
464     #endif // ndef HAVE_SDL
465    
466 cebix 1.1
467     #ifdef __mac__
468     SndChannelPtr chan1;
469     SndDoubleBufferHeader myDblHeader;
470     SndDoubleBufferPtr sampleBuffer1, sampleBuffer2;
471     SCStatus myStatus;
472     short sndbufsize;
473     OSErr err;
474    
475     static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
476     #endif
477    
478     #ifdef WIN32
479     public:
480     void VBlank(void);
481    
482     private:
483     void StartPlayer(void);
484     void StopPlayer(void);
485    
486     BOOL direct_sound;
487     DigitalPlayer *ThePlayer;
488     SWORD *sound_buffer;
489     int to_output;
490     int sb_pos;
491     int divisor;
492     int *lead;
493     int lead_pos;
494     #endif
495    
496     #ifdef __riscos__
497     int linecnt, sndbufsize;
498     uint8 *sound_buffer;
499     #endif
500     };
501    
502     // Static data members
503     uint16 DigitalRenderer::TriTable[0x1000*2];
504    
505     #ifndef EMUL_MOS8580
506     // Sampled from a 6581R4
507     const uint16 DigitalRenderer::TriSawTable[0x100] = {
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, 0x0000, 0x0808,
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, 0x1010, 0x3C3C,
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, 0x0000, 0x0808,
532     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
533     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
534     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
535     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
536     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
537     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
538     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
539     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C
540     };
541    
542     const uint16 DigitalRenderer::TriRectTable[0x100] = {
543     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
544     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
545     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
546     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
547     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
548     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
549     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
550     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
551     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
552     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
553     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
554     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
555     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
556     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
557     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0,
558     0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC,
559     0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080,
560     0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000,
561     0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
562     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
563     0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
564     0x8080, 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     0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
568     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
569     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
570     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
571     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
572     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
573     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
574     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
575     };
576    
577     const uint16 DigitalRenderer::SawRectTable[0x100] = {
578     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
579     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
580     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
581     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
582     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
583     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
584     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
585     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
586     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
587     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
588     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
589     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
590     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
591     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
592     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
593     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878,
594     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
595     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
596     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
597     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
598     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
599     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
600     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
601     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
602     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
603     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
604     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
605     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
606     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
607     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
608     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
609     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878
610     };
611    
612     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
613     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
614     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
615     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
616     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
617     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
618     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
619     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
620     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
621     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
622     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
623     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
624     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
625     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
626     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
627     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
628     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
629     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
630     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
631     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
632     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
633     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
634     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
635     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
636     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
637     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
638     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
639     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
640     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
641     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
642     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
643     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
644     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
645     };
646     #else
647     // Sampled from an 8580R5
648     const uint16 DigitalRenderer::TriSawTable[0x100] = {
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, 0x0000, 0x0808,
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, 0x1818, 0x3C3C,
665     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
666     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
667     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
668     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
669     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
670     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
671     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
672     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C,
673     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
674     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
675     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
676     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
677     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
678     0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080,
679     0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0,
680     0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE
681     };
682    
683     const uint16 DigitalRenderer::TriRectTable[0x100] = {
684     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
685     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
686     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
687     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
688     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
689     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
690     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
691     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
692     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
693     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
694     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
695     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
696     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
697     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
698     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
699     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
700     0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0,
701     0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0,
702     0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080,
703     0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000,
704     0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000,
705     0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
706     0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
707     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
708     0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000,
709     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
710     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
711     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
712     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
713     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
714     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
715     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
716     };
717    
718     const uint16 DigitalRenderer::SawRectTable[0x100] = {
719     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
720     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
721     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
722     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
723     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
724     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
725     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
726     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
727     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
728     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
729     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
730     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
731     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
732     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
733     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
734     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
735     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
736     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
737     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
738     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
739     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
740     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
741     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
742     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE,
743     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
744     0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
745     0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
746     0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC,
747     0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0,
748     0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC,
749     0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4,
750     0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF
751     };
752    
753     const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
754     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
755     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
756     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
757     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
758     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
759     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
760     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
761     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
762     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
763     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
764     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
765     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
766     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
767     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
768     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
769     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
770     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
771     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
772     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
773     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
774     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
775     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
776     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
777     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
778     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
779     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
780     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
781     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
782     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
783     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
784     0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0,
785     0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC
786     };
787     #endif
788    
789     const uint32 DigitalRenderer::EGTable[16] = {
790     (SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32,
791     (SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95,
792     (SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220,
793     (SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313,
794     (SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977,
795     (SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126,
796     (SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720,
797     (SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251
798     };
799    
800     const uint8 DigitalRenderer::EGDRShift[256] = {
801     5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,
802     3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
803     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
804     2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,
805     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
806     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
807     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
808     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
809     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
810     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
811     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
812     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
813     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
814     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
815     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
816     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
817     };
818    
819     const int16 DigitalRenderer::SampleTab[16] = {
820     0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777,
821     0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff,
822     };
823    
824    
825     /*
826     * Constructor
827     */
828    
829     DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64)
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     // Get current master volume from sample buffer,
1205     // calculate sampled voice
1206     uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE];
1207     sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ;
1208 cebix 1.7 int32 sum_output = SampleTab[master_volume] << 8;
1209     int32 sum_output_filter = 0;
1210 cebix 1.1
1211     // Loop for all three voices
1212     for (int j=0; j<3; j++) {
1213     DRVoice *v = &voice[j];
1214    
1215     // Envelope generators
1216     uint16 envelope;
1217    
1218     switch (v->eg_state) {
1219     case EG_ATTACK:
1220     v->eg_level += v->a_add;
1221     if (v->eg_level > 0xffffff) {
1222     v->eg_level = 0xffffff;
1223     v->eg_state = EG_DECAY;
1224     }
1225     break;
1226     case EG_DECAY:
1227     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1228     v->eg_level = v->s_level;
1229     else {
1230     v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16];
1231     if (v->eg_level <= v->s_level || v->eg_level > 0xffffff)
1232     v->eg_level = v->s_level;
1233     }
1234     break;
1235     case EG_RELEASE:
1236     v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16];
1237     if (v->eg_level > 0xffffff) {
1238     v->eg_level = 0;
1239     v->eg_state = EG_IDLE;
1240     }
1241     break;
1242     case EG_IDLE:
1243     v->eg_level = 0;
1244     break;
1245     }
1246     envelope = (v->eg_level * master_volume) >> 20;
1247    
1248     // Waveform generator
1249 cebix 1.3 if (v->mute)
1250     continue;
1251 cebix 1.1 uint16 output;
1252    
1253     if (!v->test)
1254     v->count += v->add;
1255    
1256     if (v->sync && (v->count > 0x1000000))
1257     v->mod_to->count = 0;
1258    
1259     v->count &= 0xffffff;
1260    
1261     switch (v->wave) {
1262     case WAVE_TRI:
1263     if (v->ring)
1264     output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11];
1265     else
1266     output = TriTable[v->count >> 11];
1267     break;
1268     case WAVE_SAW:
1269     output = v->count >> 8;
1270     break;
1271     case WAVE_RECT:
1272     if (v->count > (uint32)(v->pw << 12))
1273     output = 0xffff;
1274     else
1275     output = 0;
1276     break;
1277     case WAVE_TRISAW:
1278     output = TriSawTable[v->count >> 16];
1279     break;
1280     case WAVE_TRIRECT:
1281     if (v->count > (uint32)(v->pw << 12))
1282     output = TriRectTable[v->count >> 16];
1283     else
1284     output = 0;
1285     break;
1286     case WAVE_SAWRECT:
1287     if (v->count > (uint32)(v->pw << 12))
1288     output = SawRectTable[v->count >> 16];
1289     else
1290     output = 0;
1291     break;
1292     case WAVE_TRISAWRECT:
1293     if (v->count > (uint32)(v->pw << 12))
1294     output = TriSawRectTable[v->count >> 16];
1295     else
1296     output = 0;
1297     break;
1298     case WAVE_NOISE:
1299     if (v->count > 0x100000) {
1300     output = v->noise = sid_random() << 8;
1301     v->count &= 0xfffff;
1302     } else
1303     output = v->noise;
1304     break;
1305     default:
1306     output = 0x8000;
1307     break;
1308     }
1309     if (v->filter)
1310     sum_output_filter += (int16)(output ^ 0x8000) * envelope;
1311     else
1312     sum_output += (int16)(output ^ 0x8000) * envelope;
1313     }
1314    
1315     // Filter
1316     if (ThePrefs.SIDFilters) {
1317     #ifdef USE_FIXPOINT_MATHS
1318     int32 xn = cf_ampl.imul(sum_output_filter);
1319     int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2);
1320     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1321     sum_output_filter = yn;
1322     #else
1323     float xn = (float)sum_output_filter * cf_ampl;
1324     float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2;
1325     yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn;
1326     sum_output_filter = (int32)yn;
1327     #endif
1328     }
1329    
1330     // Write to buffer
1331 cebix 1.4 #if defined(__riscos__) // lookup in 8k (13bit) translation table
1332 cebix 1.1 *buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff];
1333     #else
1334     *buf++ = (sum_output + sum_output_filter) >> 10;
1335     #endif
1336     }
1337     }
1338    
1339    
1340     // Manufacturer independent sound is still just a dream...
1341     #if defined(__BEOS__)
1342     #include "SID_Be.h"
1343    
1344     #elif defined(AMIGA)
1345     #include "SID_Amiga.h"
1346    
1347 cebix 1.10 #elif defined(HAVE_SDL)
1348     #include "SID_SDL.h"
1349     # if defined(__linux__)
1350     # include "SID_catweasel.h"
1351     # endif
1352    
1353 cebix 1.1 #elif defined(__linux__)
1354     #include "SID_linux.h"
1355 cebix 1.10 #include "SID_catweasel.h"
1356 cebix 1.1
1357     #elif defined(SUN)
1358     #include "SID_sun.h"
1359    
1360     #elif defined(__hpux)
1361     #include "SID_hp.h"
1362    
1363     #elif defined(__mac__)
1364     #include "SID_mac.h"
1365    
1366     #elif defined(WIN32)
1367     #include "SID_WIN32.h"
1368    
1369     #elif defined(__riscos__)
1370     #include "SID_Acorn.h"
1371    
1372     #else // No sound
1373     void DigitalRenderer::init_sound(void) {ready = false;}
1374     DigitalRenderer::~DigitalRenderer() {}
1375     void DigitalRenderer::EmulateLine(void) {}
1376     void DigitalRenderer::Pause(void) {}
1377     void DigitalRenderer::Resume(void) {}
1378     #endif
1379    
1380    
1381     /*
1382     * Open/close the renderer, according to old and new prefs
1383     */
1384    
1385     void MOS6581::open_close_renderer(int old_type, int new_type)
1386     {
1387     if (old_type == new_type)
1388     return;
1389    
1390     // Delete the old renderer
1391     delete the_renderer;
1392    
1393     // Create new renderer
1394 cebix 1.9 if (new_type == SIDTYPE_DIGITAL) {
1395 cebix 1.1 the_renderer = new DigitalRenderer(the_c64);
1396     #ifdef AMIGA
1397 cebix 1.9 } else if (new_type == SIDTYPE_SIDCARD) {
1398 cebix 1.7 the_renderer = new SIDCardRenderer;
1399 cebix 1.1 #endif
1400 cebix 1.5 #ifdef __linux__
1401 cebix 1.9 } else if (new_type == SIDTYPE_SIDCARD) {
1402 cebix 1.7 the_renderer = new CatweaselRenderer;
1403 cebix 1.5 #endif
1404 cebix 1.9 } else {
1405 cebix 1.1 the_renderer = NULL;
1406 cebix 1.9 }
1407 cebix 1.1
1408     // Stuff the current register values into the new renderer
1409     if (the_renderer != NULL)
1410     for (int i=0; i<25; i++)
1411     the_renderer->WriteRegister(i, regs[i]);
1412     }