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

File Contents

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