ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/SID.cpp
Revision: 1.9
Committed: 2010-04-22T07:58:53Z (14 years ago) by cebix
Branch: MAIN
Changes since 1.8: +8 -19 lines
Log Message:
streamlining

File Contents

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