ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.3
Committed: 2003-07-09T13:46:37Z (20 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.2: +8 -8 lines
Log Message:
voice 3 mute works

File Contents

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