ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (20 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

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