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