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