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

File Contents

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