ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.8
Committed: 2005-06-27T19:55:48Z (19 years, 4 months ago) by cebix
Branch: MAIN
CVS Tags: VERSION_4_2
Changes since 1.7: +1 -1 lines
Log Message:
updated copyright dates

File Contents

# Content
1 /*
2 * SID.cpp - 6581 emulation
3 *
4 * Frodo (C) 1994-1997,2002-2005 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 #if defined(__BEOS__) || defined(__riscos__)
358 DigitalRenderer(C64 *c64);
359 #else
360 DigitalRenderer();
361 #endif
362 virtual ~DigitalRenderer();
363
364 virtual void Reset(void);
365 virtual void EmulateLine(void);
366 virtual void WriteRegister(uint16 adr, uint8 byte);
367 virtual void NewPrefs(Prefs *prefs);
368 virtual void Pause(void);
369 virtual void Resume(void);
370
371 private:
372 void init_sound(void);
373 void calc_filter(void);
374 #ifdef __riscos__
375 void calc_buffer(uint8 *buf, long count);
376 #else
377 void calc_buffer(int16 *buf, long count);
378 #endif
379
380 bool ready; // Flag: Renderer has initialized and is ready
381 uint8 volume; // Master volume
382
383 static uint16 TriTable[0x1000*2]; // Tables for certain waveforms
384 static const uint16 TriSawTable[0x100];
385 static const uint16 TriRectTable[0x100];
386 static const uint16 SawRectTable[0x100];
387 static const uint16 TriSawRectTable[0x100];
388 static const uint32 EGTable[16]; // Increment/decrement values for all A/D/R settings
389 static const uint8 EGDRShift[256]; // For exponential approximation of D/R
390 static const int16 SampleTab[16]; // Table for sampled voice
391
392 DRVoice voice[3]; // Data for 3 voices
393
394 uint8 f_type; // Filter type
395 uint8 f_freq; // SID filter frequency (upper 8 bits)
396 uint8 f_res; // Filter resonance (0..15)
397 #ifdef USE_FIXPOINT_MATHS
398 FixPoint f_ampl;
399 FixPoint d1, d2, g1, g2;
400 int32 xn1, xn2, yn1, yn2; // can become very large
401 FixPoint sidquot;
402 #ifdef PRECOMPUTE_RESONANCE
403 FixPoint resonanceLP[256];
404 FixPoint resonanceHP[256];
405 #endif
406 #else
407 float f_ampl; // IIR filter input attenuation
408 float d1, d2, g1, g2; // IIR filter coefficients
409 float xn1, xn2, yn1, yn2; // IIR filter previous input/output signal
410 #ifdef PRECOMPUTE_RESONANCE
411 float resonanceLP[256]; // shortcut for calc_filter
412 float resonanceHP[256];
413 #endif
414 #endif
415
416 uint8 sample_buf[SAMPLE_BUF_SIZE]; // Buffer for sampled voice
417 int sample_in_ptr; // Index in sample_buf for writing
418
419 #ifdef __BEOS__
420 static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format);
421 C64 *the_c64; // Pointer to C64 object
422 BSoundPlayer *the_player; // Pointer to sound player
423 bool player_stopped; // Flag: player stopped
424 #endif
425
426 #ifdef AMIGA
427 static void sub_invoc(void); // Sound sub-process
428 void sub_func(void);
429 struct Process *sound_process;
430 int quit_sig, pause_sig,
431 resume_sig, ahi_sig; // Sub-process signals
432 struct Task *main_task; // Main task
433 int main_sig; // Main task signals
434 static ULONG sound_func(void); // AHI callback
435 struct MsgPort *ahi_port; // Port and IORequest for AHI
436 struct AHIRequest *ahi_io;
437 struct AHIAudioCtrl *ahi_ctrl; // AHI control structure
438 struct AHISampleInfo sample[2]; // SampleInfos for double buffering
439 struct Hook sf_hook; // Hook for callback function
440 int play_buf; // Number of buffer currently playing
441 #endif
442
443 #ifdef __linux__
444 int devfd, sndbufsize, buffer_rate;
445 int16 *sound_buffer;
446 #endif
447
448 #ifdef SUN
449 int fd;
450 audio_info status;
451 uint_t sent_samples,delta_samples;
452 int16 *sound_calc_buf;
453 #endif
454
455 #ifdef __hpux
456 int fd;
457 audio_status status;
458 int16 *sound_calc_buf;
459 int linecnt;
460 #endif
461
462 #ifdef __mac__
463 SndChannelPtr chan1;
464 SndDoubleBufferHeader myDblHeader;
465 SndDoubleBufferPtr sampleBuffer1, sampleBuffer2;
466 SCStatus myStatus;
467 short sndbufsize;
468 OSErr err;
469
470 static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
471 #endif
472
473 #ifdef WIN32
474 public:
475 void VBlank(void);
476
477 private:
478 void StartPlayer(void);
479 void StopPlayer(void);
480
481 BOOL direct_sound;
482 DigitalPlayer *ThePlayer;
483 SWORD *sound_buffer;
484 int to_output;
485 int sb_pos;
486 int divisor;
487 int *lead;
488 int lead_pos;
489 #endif
490
491 #ifdef __riscos__
492 int linecnt, sndbufsize;
493 uint8 *sound_buffer;
494 C64 *the_c64;
495 #endif
496 };
497
498 // Static data members
499 uint16 DigitalRenderer::TriTable[0x1000*2];
500
501 #ifndef EMUL_MOS8580
502 // Sampled from a 6581R4
503 const uint16 DigitalRenderer::TriSawTable[0x100] = {
504 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
505 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
506 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
507 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
508 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
509 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
510 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
511 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
512 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
513 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
514 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
515 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
516 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
517 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
518 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
519 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C,
520 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
521 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
522 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
523 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
524 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
525 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
526 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
527 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
528 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
529 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
530 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
531 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
532 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
533 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
534 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
535 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C
536 };
537
538 const uint16 DigitalRenderer::TriRectTable[0x100] = {
539 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
540 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
541 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
542 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
543 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
544 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
545 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
546 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
547 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
548 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
549 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
550 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
551 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
552 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
553 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0,
554 0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC,
555 0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080,
556 0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000,
557 0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
558 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
559 0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000,
560 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
561 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
562 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
563 0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
564 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
565 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
566 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
567 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
568 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
569 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
570 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
571 };
572
573 const uint16 DigitalRenderer::SawRectTable[0x100] = {
574 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
575 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
576 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
577 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
578 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
579 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
580 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
581 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
582 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
583 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
584 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
585 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
586 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
587 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
588 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
589 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878,
590 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
591 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
592 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
593 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
594 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
595 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
596 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
597 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
598 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
599 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
600 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
601 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
602 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
603 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
604 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
605 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878
606 };
607
608 const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
609 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
610 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
611 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
612 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
613 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
614 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
615 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
616 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
617 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
618 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
619 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
620 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
621 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
622 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
623 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
624 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
625 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
626 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
627 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
628 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
629 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
630 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
631 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
632 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
633 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
634 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
635 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
636 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
637 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
638 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
639 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
640 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
641 };
642 #else
643 // Sampled from an 8580R5
644 const uint16 DigitalRenderer::TriSawTable[0x100] = {
645 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
646 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
647 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
648 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
649 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
650 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
651 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
652 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808,
653 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
654 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
655 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
656 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
657 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
658 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
659 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
660 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x3C3C,
661 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
662 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
663 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
664 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
665 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
666 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
667 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
668 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C,
669 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
670 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
671 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
672 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
673 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
674 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080,
675 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0,
676 0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE
677 };
678
679 const uint16 DigitalRenderer::TriRectTable[0x100] = {
680 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
681 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
682 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
683 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
684 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
685 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
686 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
687 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
688 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
689 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
690 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
691 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
692 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
693 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
694 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
695 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
696 0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0,
697 0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0,
698 0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080,
699 0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000,
700 0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000,
701 0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
702 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
703 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
704 0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000,
705 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
706 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
707 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
708 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
709 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
710 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
711 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
712 };
713
714 const uint16 DigitalRenderer::SawRectTable[0x100] = {
715 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
716 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
717 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
718 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
719 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
720 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
721 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
722 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
723 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
724 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
725 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
726 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
727 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
728 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
729 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
730 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
731 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
732 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
733 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
734 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
735 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
736 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
737 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
738 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE,
739 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080,
740 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
741 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0,
742 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC,
743 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0,
744 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC,
745 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4,
746 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF
747 };
748
749 const uint16 DigitalRenderer::TriSawRectTable[0x100] = {
750 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
751 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
752 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
753 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
754 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
755 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
756 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
757 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
758 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
759 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
760 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
761 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
762 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
763 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
764 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
765 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
766 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
767 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
768 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
769 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
770 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
771 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
772 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
773 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
774 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
775 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
776 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
777 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
778 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
779 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080,
780 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0,
781 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC
782 };
783 #endif
784
785 const uint32 DigitalRenderer::EGTable[16] = {
786 (SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32,
787 (SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95,
788 (SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220,
789 (SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313,
790 (SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977,
791 (SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126,
792 (SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720,
793 (SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251
794 };
795
796 const uint8 DigitalRenderer::EGDRShift[256] = {
797 5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,
798 3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,
799 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
800 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,
801 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
802 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
803 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
804 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
805 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
806 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
807 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
808 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
809 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
810 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
811 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
812 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
813 };
814
815 const int16 DigitalRenderer::SampleTab[16] = {
816 0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777,
817 0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff,
818 };
819
820
821 /*
822 * Constructor
823 */
824
825 #if defined(__BEOS__) || defined(__riscos__)
826 DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64)
827 #else
828 DigitalRenderer::DigitalRenderer()
829 #endif
830 {
831 // Link voices together
832 voice[0].mod_by = &voice[2];
833 voice[1].mod_by = &voice[0];
834 voice[2].mod_by = &voice[1];
835 voice[0].mod_to = &voice[1];
836 voice[1].mod_to = &voice[2];
837 voice[2].mod_to = &voice[0];
838
839 // Calculate triangle table
840 for (int i=0; i<0x1000; i++) {
841 TriTable[i] = (i << 4) | (i >> 8);
842 TriTable[0x1fff-i] = (i << 4) | (i >> 8);
843 }
844
845 #ifdef PRECOMPUTE_RESONANCE
846 #ifdef USE_FIXPOINT_MATHS
847 // slow floating point doesn't matter much on startup!
848 for (int i=0; i<256; i++) {
849 resonanceLP[i] = FixNo(CALC_RESONANCE_LP(i));
850 resonanceHP[i] = FixNo(CALC_RESONANCE_HP(i));
851 }
852 // Pre-compute the quotient. No problem since int-part is small enough
853 sidquot = (int32)((((double)SID_FREQ)*65536) / SAMPLE_FREQ);
854 // compute lookup table for sin and cos
855 InitFixSinTab();
856 #else
857 for (int i=0; i<256; i++) {
858 resonanceLP[i] = CALC_RESONANCE_LP(i);
859 resonanceHP[i] = CALC_RESONANCE_HP(i);
860 }
861 #endif
862 #endif
863
864 Reset();
865
866 // System specific initialization
867 init_sound();
868 }
869
870
871 /*
872 * Reset emulation
873 */
874
875 void DigitalRenderer::Reset(void)
876 {
877 volume = 0;
878
879 for (int v=0; v<3; v++) {
880 voice[v].wave = WAVE_NONE;
881 voice[v].eg_state = EG_IDLE;
882 voice[v].count = voice[v].add = 0;
883 voice[v].freq = voice[v].pw = 0;
884 voice[v].eg_level = voice[v].s_level = 0;
885 voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0];
886 voice[v].gate = voice[v].ring = voice[v].test = false;
887 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(__linux__)
1348 #include "SID_linux.h"
1349
1350 #elif defined(SUN)
1351 #include "SID_sun.h"
1352
1353 #elif defined(__hpux)
1354 #include "SID_hp.h"
1355
1356 #elif defined(__mac__)
1357 #include "SID_mac.h"
1358
1359 #elif defined(WIN32)
1360 #include "SID_WIN32.h"
1361
1362 #elif defined(__riscos__)
1363 #include "SID_Acorn.h"
1364
1365 #else // No sound
1366 void DigitalRenderer::init_sound(void) {ready = false;}
1367 DigitalRenderer::~DigitalRenderer() {}
1368 void DigitalRenderer::EmulateLine(void) {}
1369 void DigitalRenderer::Pause(void) {}
1370 void DigitalRenderer::Resume(void) {}
1371 #endif
1372
1373
1374 /*
1375 * Open/close the renderer, according to old and new prefs
1376 */
1377
1378 void MOS6581::open_close_renderer(int old_type, int new_type)
1379 {
1380 if (old_type == new_type)
1381 return;
1382
1383 // Delete the old renderer
1384 delete the_renderer;
1385
1386 // Create new renderer
1387 if (new_type == SIDTYPE_DIGITAL)
1388 #if defined(__BEOS__) || defined(__riscos__)
1389 the_renderer = new DigitalRenderer(the_c64);
1390 #else
1391 the_renderer = new DigitalRenderer;
1392 #endif
1393 #ifdef AMIGA
1394 else if (new_type == SIDTYPE_SIDCARD)
1395 the_renderer = new SIDCardRenderer;
1396 #endif
1397 #ifdef __linux__
1398 else if (new_type == SIDTYPE_SIDCARD)
1399 the_renderer = new CatweaselRenderer;
1400 #endif
1401 else
1402 the_renderer = NULL;
1403
1404 // Stuff the current register values into the new renderer
1405 if (the_renderer != NULL)
1406 for (int i=0; i<25; i++)
1407 the_renderer->WriteRegister(i, regs[i]);
1408 }