1 |
cebix |
1.1 |
/* |
2 |
|
|
* SID.cpp - 6581 emulation |
3 |
|
|
* |
4 |
cebix |
1.6 |
* Frodo (C) 1994-1997,2002-2004 Christian Bauer |
5 |
cebix |
1.1 |
* |
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 |
cebix |
1.4 |
#include <media/SoundPlayer.h> |
36 |
cebix |
1.1 |
#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 |
cebix |
1.3 |
bool mute; // Voice muted (voice 3 only) |
352 |
cebix |
1.1 |
}; |
353 |
|
|
|
354 |
|
|
// Renderer class |
355 |
|
|
class DigitalRenderer : public SIDRenderer { |
356 |
|
|
public: |
357 |
|
|
#if defined(__BEOS__) || defined(__riscos__) |
358 |
|
|
DigitalRenderer(C64 *c64); |
359 |
|
|
#else |
360 |
|
|
DigitalRenderer(); |
361 |
|
|
#endif |
362 |
|
|
virtual ~DigitalRenderer(); |
363 |
|
|
|
364 |
|
|
virtual void Reset(void); |
365 |
|
|
virtual void EmulateLine(void); |
366 |
|
|
virtual void WriteRegister(uint16 adr, uint8 byte); |
367 |
|
|
virtual void NewPrefs(Prefs *prefs); |
368 |
|
|
virtual void Pause(void); |
369 |
|
|
virtual void Resume(void); |
370 |
|
|
|
371 |
|
|
private: |
372 |
|
|
void init_sound(void); |
373 |
|
|
void calc_filter(void); |
374 |
|
|
#ifdef __riscos__ |
375 |
|
|
void calc_buffer(uint8 *buf, long count); |
376 |
|
|
#else |
377 |
|
|
void calc_buffer(int16 *buf, long count); |
378 |
|
|
#endif |
379 |
|
|
|
380 |
|
|
bool ready; // Flag: Renderer has initialized and is ready |
381 |
|
|
uint8 volume; // Master volume |
382 |
|
|
|
383 |
|
|
static uint16 TriTable[0x1000*2]; // Tables for certain waveforms |
384 |
|
|
static const uint16 TriSawTable[0x100]; |
385 |
|
|
static const uint16 TriRectTable[0x100]; |
386 |
|
|
static const uint16 SawRectTable[0x100]; |
387 |
|
|
static const uint16 TriSawRectTable[0x100]; |
388 |
|
|
static const uint32 EGTable[16]; // Increment/decrement values for all A/D/R settings |
389 |
|
|
static const uint8 EGDRShift[256]; // For exponential approximation of D/R |
390 |
|
|
static const int16 SampleTab[16]; // Table for sampled voice |
391 |
|
|
|
392 |
|
|
DRVoice voice[3]; // Data for 3 voices |
393 |
|
|
|
394 |
|
|
uint8 f_type; // Filter type |
395 |
|
|
uint8 f_freq; // SID filter frequency (upper 8 bits) |
396 |
|
|
uint8 f_res; // Filter resonance (0..15) |
397 |
|
|
#ifdef USE_FIXPOINT_MATHS |
398 |
|
|
FixPoint f_ampl; |
399 |
|
|
FixPoint d1, d2, g1, g2; |
400 |
|
|
int32 xn1, xn2, yn1, yn2; // can become very large |
401 |
|
|
FixPoint sidquot; |
402 |
|
|
#ifdef PRECOMPUTE_RESONANCE |
403 |
|
|
FixPoint resonanceLP[256]; |
404 |
|
|
FixPoint resonanceHP[256]; |
405 |
|
|
#endif |
406 |
|
|
#else |
407 |
|
|
float f_ampl; // IIR filter input attenuation |
408 |
|
|
float d1, d2, g1, g2; // IIR filter coefficients |
409 |
|
|
float xn1, xn2, yn1, yn2; // IIR filter previous input/output signal |
410 |
|
|
#ifdef PRECOMPUTE_RESONANCE |
411 |
|
|
float resonanceLP[256]; // shortcut for calc_filter |
412 |
|
|
float resonanceHP[256]; |
413 |
|
|
#endif |
414 |
|
|
#endif |
415 |
|
|
|
416 |
|
|
uint8 sample_buf[SAMPLE_BUF_SIZE]; // Buffer for sampled voice |
417 |
|
|
int sample_in_ptr; // Index in sample_buf for writing |
418 |
|
|
|
419 |
|
|
#ifdef __BEOS__ |
420 |
cebix |
1.4 |
static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format); |
421 |
cebix |
1.1 |
C64 *the_c64; // Pointer to C64 object |
422 |
cebix |
1.4 |
BSoundPlayer *the_player; // Pointer to sound player |
423 |
|
|
bool player_stopped; // Flag: player stopped |
424 |
cebix |
1.1 |
#endif |
425 |
|
|
|
426 |
|
|
#ifdef AMIGA |
427 |
|
|
static void sub_invoc(void); // Sound sub-process |
428 |
|
|
void sub_func(void); |
429 |
|
|
struct Process *sound_process; |
430 |
|
|
int quit_sig, pause_sig, |
431 |
|
|
resume_sig, ahi_sig; // Sub-process signals |
432 |
|
|
struct Task *main_task; // Main task |
433 |
|
|
int main_sig; // Main task signals |
434 |
|
|
static ULONG sound_func(void); // AHI callback |
435 |
|
|
struct MsgPort *ahi_port; // Port and IORequest for AHI |
436 |
|
|
struct AHIRequest *ahi_io; |
437 |
|
|
struct AHIAudioCtrl *ahi_ctrl; // AHI control structure |
438 |
|
|
struct AHISampleInfo sample[2]; // SampleInfos for double buffering |
439 |
|
|
struct Hook sf_hook; // Hook for callback function |
440 |
|
|
int play_buf; // Number of buffer currently playing |
441 |
|
|
#endif |
442 |
|
|
|
443 |
|
|
#ifdef __linux__ |
444 |
|
|
int devfd, sndbufsize, buffer_rate; |
445 |
|
|
int16 *sound_buffer; |
446 |
|
|
#endif |
447 |
|
|
|
448 |
|
|
#ifdef SUN |
449 |
|
|
int fd; |
450 |
|
|
audio_info status; |
451 |
|
|
uint_t sent_samples,delta_samples; |
452 |
cebix |
1.3 |
int16 *sound_calc_buf; |
453 |
cebix |
1.1 |
#endif |
454 |
|
|
|
455 |
|
|
#ifdef __hpux |
456 |
|
|
int fd; |
457 |
|
|
audio_status status; |
458 |
cebix |
1.3 |
int16 *sound_calc_buf; |
459 |
cebix |
1.1 |
int linecnt; |
460 |
|
|
#endif |
461 |
|
|
|
462 |
|
|
#ifdef __mac__ |
463 |
|
|
SndChannelPtr chan1; |
464 |
|
|
SndDoubleBufferHeader myDblHeader; |
465 |
|
|
SndDoubleBufferPtr sampleBuffer1, sampleBuffer2; |
466 |
|
|
SCStatus myStatus; |
467 |
|
|
short sndbufsize; |
468 |
|
|
OSErr err; |
469 |
|
|
|
470 |
|
|
static void doubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer); |
471 |
|
|
#endif |
472 |
|
|
|
473 |
|
|
#ifdef WIN32 |
474 |
|
|
public: |
475 |
|
|
void VBlank(void); |
476 |
|
|
|
477 |
|
|
private: |
478 |
|
|
void StartPlayer(void); |
479 |
|
|
void StopPlayer(void); |
480 |
|
|
|
481 |
|
|
BOOL direct_sound; |
482 |
|
|
DigitalPlayer *ThePlayer; |
483 |
|
|
SWORD *sound_buffer; |
484 |
|
|
int to_output; |
485 |
|
|
int sb_pos; |
486 |
|
|
int divisor; |
487 |
|
|
int *lead; |
488 |
|
|
int lead_pos; |
489 |
|
|
#endif |
490 |
|
|
|
491 |
|
|
#ifdef __riscos__ |
492 |
|
|
int linecnt, sndbufsize; |
493 |
|
|
uint8 *sound_buffer; |
494 |
|
|
C64 *the_c64; |
495 |
|
|
#endif |
496 |
|
|
}; |
497 |
|
|
|
498 |
|
|
// Static data members |
499 |
|
|
uint16 DigitalRenderer::TriTable[0x1000*2]; |
500 |
|
|
|
501 |
|
|
#ifndef EMUL_MOS8580 |
502 |
|
|
// Sampled from a 6581R4 |
503 |
|
|
const uint16 DigitalRenderer::TriSawTable[0x100] = { |
504 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
505 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
506 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
507 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
508 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
509 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
510 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
511 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, |
512 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
513 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
514 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
515 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
516 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
517 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
518 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
519 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C, |
520 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
521 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
522 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
523 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
524 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
525 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
526 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
527 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, |
528 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
529 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
530 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
531 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
532 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
533 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
534 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
535 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x3C3C |
536 |
|
|
}; |
537 |
|
|
|
538 |
|
|
const uint16 DigitalRenderer::TriRectTable[0x100] = { |
539 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
540 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
541 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
542 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
543 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
544 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
545 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
546 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
547 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
548 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
549 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
550 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, |
551 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
552 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, |
553 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0xC0C0, |
554 |
|
|
0x0000, 0x8080, 0x8080, 0xE0E0, 0x8080, 0xE0E0, 0xF0F0, 0xFCFC, |
555 |
|
|
0xFFFF, 0xFCFC, 0xFAFA, 0xF0F0, 0xF6F6, 0xE0E0, 0xE0E0, 0x8080, |
556 |
|
|
0xEEEE, 0xE0E0, 0xE0E0, 0x8080, 0xC0C0, 0x0000, 0x0000, 0x0000, |
557 |
|
|
0xDEDE, 0xC0C0, 0xC0C0, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000, |
558 |
|
|
0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
559 |
|
|
0xBEBE, 0x8080, 0x8080, 0x0000, 0x8080, 0x0000, 0x0000, 0x0000, |
560 |
|
|
0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
561 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
562 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
563 |
|
|
0x7E7E, 0x4040, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
564 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
565 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
566 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
567 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
568 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
569 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
570 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
571 |
|
|
}; |
572 |
|
|
|
573 |
|
|
const uint16 DigitalRenderer::SawRectTable[0x100] = { |
574 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
575 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
576 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
577 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
578 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
579 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
580 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
581 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
582 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
583 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
584 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
585 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
586 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
587 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
588 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
589 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878, |
590 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
591 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
592 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
593 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
594 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
595 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
596 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
597 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
598 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
599 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
600 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
601 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
602 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
603 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
604 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
605 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7878 |
606 |
|
|
}; |
607 |
|
|
|
608 |
|
|
const uint16 DigitalRenderer::TriSawRectTable[0x100] = { |
609 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
610 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
611 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
612 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
613 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
614 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
615 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
616 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
617 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
618 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
619 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
620 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
621 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
622 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
623 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
624 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
625 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
626 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
627 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
628 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
629 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
630 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
631 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
632 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
633 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
634 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
635 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
636 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
637 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
638 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
639 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
640 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
641 |
|
|
}; |
642 |
|
|
#else |
643 |
|
|
// Sampled from an 8580R5 |
644 |
|
|
const uint16 DigitalRenderer::TriSawTable[0x100] = { |
645 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
646 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
647 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
648 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
649 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
650 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
651 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
652 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0808, |
653 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
654 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
655 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
656 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
657 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
658 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
659 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
660 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x3C3C, |
661 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
662 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
663 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
664 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
665 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
666 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
667 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
668 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C1C, |
669 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
670 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
671 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
672 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
673 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
674 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x0000, 0x8080, 0x8080, |
675 |
|
|
0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, |
676 |
|
|
0xF0F0, 0xF0F0, 0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE |
677 |
|
|
}; |
678 |
|
|
|
679 |
|
|
const uint16 DigitalRenderer::TriRectTable[0x100] = { |
680 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
681 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
682 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
683 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
684 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
685 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
686 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
687 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
688 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
689 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
690 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
691 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
692 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
693 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
694 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
695 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
696 |
|
|
0xFFFF, 0xFCFC, 0xF8F8, 0xF0F0, 0xF4F4, 0xF0F0, 0xF0F0, 0xE0E0, |
697 |
|
|
0xECEC, 0xE0E0, 0xE0E0, 0xC0C0, 0xE0E0, 0xC0C0, 0xC0C0, 0xC0C0, |
698 |
|
|
0xDCDC, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0x8080, 0x8080, |
699 |
|
|
0xC0C0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, 0x0000, |
700 |
|
|
0xBEBE, 0xA0A0, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0000, |
701 |
|
|
0x8080, 0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
702 |
|
|
0x8080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
703 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
704 |
|
|
0x7E7E, 0x7070, 0x6060, 0x0000, 0x4040, 0x0000, 0x0000, 0x0000, |
705 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
706 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
707 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
708 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
709 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
710 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
711 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 |
712 |
|
|
}; |
713 |
|
|
|
714 |
|
|
const uint16 DigitalRenderer::SawRectTable[0x100] = { |
715 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
716 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
717 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
718 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
719 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
720 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
721 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
722 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
723 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
724 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
725 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
726 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
727 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
728 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
729 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
730 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
731 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
732 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
733 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
734 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
735 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
736 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, |
737 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, |
738 |
|
|
0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xB0B0, 0xBEBE, |
739 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, |
740 |
|
|
0x0000, 0x0000, 0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, |
741 |
|
|
0x0000, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, |
742 |
|
|
0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xDCDC, |
743 |
|
|
0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, |
744 |
|
|
0xC0C0, 0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xECEC, |
745 |
|
|
0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF0F0, 0xF4F4, |
746 |
|
|
0xF0F0, 0xF0F0, 0xF8F8, 0xF8F8, 0xF8F8, 0xFCFC, 0xFEFE, 0xFFFF |
747 |
|
|
}; |
748 |
|
|
|
749 |
|
|
const uint16 DigitalRenderer::TriSawRectTable[0x100] = { |
750 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
751 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
752 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
753 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
754 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
755 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
756 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
757 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
758 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
759 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
760 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
761 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
762 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
763 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
764 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
765 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
766 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
767 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
768 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
769 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
770 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
771 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
772 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
773 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
774 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
775 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
776 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
777 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
778 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
779 |
|
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8080, 0x8080, |
780 |
|
|
0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0xC0C0, 0xC0C0, |
781 |
|
|
0xC0C0, 0xC0C0, 0xE0E0, 0xE0E0, 0xE0E0, 0xF0F0, 0xF8F8, 0xFCFC |
782 |
|
|
}; |
783 |
|
|
#endif |
784 |
|
|
|
785 |
|
|
const uint32 DigitalRenderer::EGTable[16] = { |
786 |
|
|
(SID_CYCLES << 16) / 9, (SID_CYCLES << 16) / 32, |
787 |
|
|
(SID_CYCLES << 16) / 63, (SID_CYCLES << 16) / 95, |
788 |
|
|
(SID_CYCLES << 16) / 149, (SID_CYCLES << 16) / 220, |
789 |
|
|
(SID_CYCLES << 16) / 267, (SID_CYCLES << 16) / 313, |
790 |
|
|
(SID_CYCLES << 16) / 392, (SID_CYCLES << 16) / 977, |
791 |
|
|
(SID_CYCLES << 16) / 1954, (SID_CYCLES << 16) / 3126, |
792 |
|
|
(SID_CYCLES << 16) / 3906, (SID_CYCLES << 16) / 11720, |
793 |
|
|
(SID_CYCLES << 16) / 19531, (SID_CYCLES << 16) / 31251 |
794 |
|
|
}; |
795 |
|
|
|
796 |
|
|
const uint8 DigitalRenderer::EGDRShift[256] = { |
797 |
|
|
5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4, |
798 |
|
|
3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, |
799 |
|
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, |
800 |
|
|
2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1, |
801 |
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, |
802 |
|
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, |
803 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
804 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
805 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
806 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
807 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
808 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
809 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
810 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
811 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
812 |
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
813 |
|
|
}; |
814 |
|
|
|
815 |
|
|
const int16 DigitalRenderer::SampleTab[16] = { |
816 |
|
|
0x8000, 0x9111, 0xa222, 0xb333, 0xc444, 0xd555, 0xe666, 0xf777, |
817 |
|
|
0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff, |
818 |
|
|
}; |
819 |
|
|
|
820 |
|
|
|
821 |
|
|
/* |
822 |
|
|
* Constructor |
823 |
|
|
*/ |
824 |
|
|
|
825 |
|
|
#if defined(__BEOS__) || defined(__riscos__) |
826 |
|
|
DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64) |
827 |
|
|
#else |
828 |
|
|
DigitalRenderer::DigitalRenderer() |
829 |
|
|
#endif |
830 |
|
|
{ |
831 |
|
|
// Link voices together |
832 |
|
|
voice[0].mod_by = &voice[2]; |
833 |
|
|
voice[1].mod_by = &voice[0]; |
834 |
|
|
voice[2].mod_by = &voice[1]; |
835 |
|
|
voice[0].mod_to = &voice[1]; |
836 |
|
|
voice[1].mod_to = &voice[2]; |
837 |
|
|
voice[2].mod_to = &voice[0]; |
838 |
|
|
|
839 |
|
|
// Calculate triangle table |
840 |
|
|
for (int i=0; i<0x1000; i++) { |
841 |
|
|
TriTable[i] = (i << 4) | (i >> 8); |
842 |
|
|
TriTable[0x1fff-i] = (i << 4) | (i >> 8); |
843 |
|
|
} |
844 |
|
|
|
845 |
|
|
#ifdef PRECOMPUTE_RESONANCE |
846 |
|
|
#ifdef USE_FIXPOINT_MATHS |
847 |
|
|
// slow floating point doesn't matter much on startup! |
848 |
|
|
for (int i=0; i<256; i++) { |
849 |
|
|
resonanceLP[i] = FixNo(CALC_RESONANCE_LP(i)); |
850 |
|
|
resonanceHP[i] = FixNo(CALC_RESONANCE_HP(i)); |
851 |
|
|
} |
852 |
|
|
// Pre-compute the quotient. No problem since int-part is small enough |
853 |
|
|
sidquot = (int32)((((double)SID_FREQ)*65536) / SAMPLE_FREQ); |
854 |
|
|
// compute lookup table for sin and cos |
855 |
|
|
InitFixSinTab(); |
856 |
|
|
#else |
857 |
|
|
for (int i=0; i<256; i++) { |
858 |
|
|
resonanceLP[i] = CALC_RESONANCE_LP(i); |
859 |
|
|
resonanceHP[i] = CALC_RESONANCE_HP(i); |
860 |
|
|
} |
861 |
|
|
#endif |
862 |
|
|
#endif |
863 |
|
|
|
864 |
|
|
Reset(); |
865 |
|
|
|
866 |
|
|
// System specific initialization |
867 |
|
|
init_sound(); |
868 |
|
|
} |
869 |
|
|
|
870 |
|
|
|
871 |
|
|
/* |
872 |
|
|
* Reset emulation |
873 |
|
|
*/ |
874 |
|
|
|
875 |
|
|
void DigitalRenderer::Reset(void) |
876 |
|
|
{ |
877 |
|
|
volume = 0; |
878 |
|
|
|
879 |
|
|
for (int v=0; v<3; v++) { |
880 |
|
|
voice[v].wave = WAVE_NONE; |
881 |
|
|
voice[v].eg_state = EG_IDLE; |
882 |
|
|
voice[v].count = voice[v].add = 0; |
883 |
|
|
voice[v].freq = voice[v].pw = 0; |
884 |
|
|
voice[v].eg_level = voice[v].s_level = 0; |
885 |
|
|
voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0]; |
886 |
|
|
voice[v].gate = voice[v].ring = voice[v].test = false; |
887 |
cebix |
1.3 |
voice[v].filter = voice[v].sync = voice[v].mute = false; |
888 |
cebix |
1.1 |
} |
889 |
|
|
|
890 |
|
|
f_type = FILT_NONE; |
891 |
|
|
f_freq = f_res = 0; |
892 |
|
|
#ifdef USE_FIXPOINT_MATHS |
893 |
|
|
f_ampl = FixNo(1); |
894 |
|
|
d1 = d2 = g1 = g2 = 0; |
895 |
|
|
xn1 = xn2 = yn1 = yn2 = 0; |
896 |
|
|
#else |
897 |
|
|
f_ampl = 1.0; |
898 |
|
|
d1 = d2 = g1 = g2 = 0.0; |
899 |
|
|
xn1 = xn2 = yn1 = yn2 = 0.0; |
900 |
|
|
#endif |
901 |
|
|
|
902 |
|
|
sample_in_ptr = 0; |
903 |
|
|
memset(sample_buf, 0, SAMPLE_BUF_SIZE); |
904 |
|
|
} |
905 |
|
|
|
906 |
|
|
|
907 |
|
|
/* |
908 |
|
|
* Write to register |
909 |
|
|
*/ |
910 |
|
|
|
911 |
|
|
void DigitalRenderer::WriteRegister(uint16 adr, uint8 byte) |
912 |
|
|
{ |
913 |
|
|
if (!ready) |
914 |
|
|
return; |
915 |
|
|
|
916 |
|
|
int v = adr/7; // Voice number |
917 |
|
|
|
918 |
|
|
switch (adr) { |
919 |
|
|
case 0: |
920 |
|
|
case 7: |
921 |
|
|
case 14: |
922 |
|
|
voice[v].freq = (voice[v].freq & 0xff00) | byte; |
923 |
|
|
#ifdef USE_FIXPOINT_MATHS |
924 |
|
|
voice[v].add = sidquot.imul((int)voice[v].freq); |
925 |
|
|
#else |
926 |
|
|
voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ); |
927 |
|
|
#endif |
928 |
|
|
break; |
929 |
|
|
|
930 |
|
|
case 1: |
931 |
|
|
case 8: |
932 |
|
|
case 15: |
933 |
|
|
voice[v].freq = (voice[v].freq & 0xff) | (byte << 8); |
934 |
|
|
#ifdef USE_FIXPOINT_MATHS |
935 |
|
|
voice[v].add = sidquot.imul((int)voice[v].freq); |
936 |
|
|
#else |
937 |
|
|
voice[v].add = (uint32)((float)voice[v].freq * SID_FREQ / SAMPLE_FREQ); |
938 |
|
|
#endif |
939 |
|
|
break; |
940 |
|
|
|
941 |
|
|
case 2: |
942 |
|
|
case 9: |
943 |
|
|
case 16: |
944 |
|
|
voice[v].pw = (voice[v].pw & 0x0f00) | byte; |
945 |
|
|
break; |
946 |
|
|
|
947 |
|
|
case 3: |
948 |
|
|
case 10: |
949 |
|
|
case 17: |
950 |
|
|
voice[v].pw = (voice[v].pw & 0xff) | ((byte & 0xf) << 8); |
951 |
|
|
break; |
952 |
|
|
|
953 |
|
|
case 4: |
954 |
|
|
case 11: |
955 |
|
|
case 18: |
956 |
|
|
voice[v].wave = (byte >> 4) & 0xf; |
957 |
|
|
if ((byte & 1) != voice[v].gate) |
958 |
|
|
if (byte & 1) // Gate turned on |
959 |
|
|
voice[v].eg_state = EG_ATTACK; |
960 |
|
|
else // Gate turned off |
961 |
|
|
if (voice[v].eg_state != EG_IDLE) |
962 |
|
|
voice[v].eg_state = EG_RELEASE; |
963 |
|
|
voice[v].gate = byte & 1; |
964 |
|
|
voice[v].mod_by->sync = byte & 2; |
965 |
|
|
voice[v].ring = byte & 4; |
966 |
cebix |
1.3 |
if ((voice[v].test = byte & 8) != 0) |
967 |
cebix |
1.1 |
voice[v].count = 0; |
968 |
|
|
break; |
969 |
|
|
|
970 |
|
|
case 5: |
971 |
|
|
case 12: |
972 |
|
|
case 19: |
973 |
|
|
voice[v].a_add = EGTable[byte >> 4]; |
974 |
|
|
voice[v].d_sub = EGTable[byte & 0xf]; |
975 |
|
|
break; |
976 |
|
|
|
977 |
|
|
case 6: |
978 |
|
|
case 13: |
979 |
|
|
case 20: |
980 |
|
|
voice[v].s_level = (byte >> 4) * 0x111111; |
981 |
|
|
voice[v].r_sub = EGTable[byte & 0xf]; |
982 |
|
|
break; |
983 |
|
|
|
984 |
|
|
case 22: |
985 |
|
|
if (byte != f_freq) { |
986 |
|
|
f_freq = byte; |
987 |
|
|
if (ThePrefs.SIDFilters) |
988 |
|
|
calc_filter(); |
989 |
|
|
} |
990 |
|
|
break; |
991 |
|
|
|
992 |
|
|
case 23: |
993 |
|
|
voice[0].filter = byte & 1; |
994 |
|
|
voice[1].filter = byte & 2; |
995 |
|
|
voice[2].filter = byte & 4; |
996 |
|
|
if ((byte >> 4) != f_res) { |
997 |
|
|
f_res = byte >> 4; |
998 |
|
|
if (ThePrefs.SIDFilters) |
999 |
|
|
calc_filter(); |
1000 |
|
|
} |
1001 |
|
|
break; |
1002 |
|
|
|
1003 |
|
|
case 24: |
1004 |
|
|
volume = byte & 0xf; |
1005 |
cebix |
1.3 |
voice[2].mute = byte & 0x80; |
1006 |
cebix |
1.1 |
if (((byte >> 4) & 7) != f_type) { |
1007 |
|
|
f_type = (byte >> 4) & 7; |
1008 |
|
|
#ifdef USE_FIXPOINT_MATHS |
1009 |
|
|
xn1 = xn2 = yn1 = yn2 = 0; |
1010 |
|
|
#else |
1011 |
|
|
xn1 = xn2 = yn1 = yn2 = 0.0; |
1012 |
|
|
#endif |
1013 |
|
|
if (ThePrefs.SIDFilters) |
1014 |
|
|
calc_filter(); |
1015 |
|
|
} |
1016 |
|
|
break; |
1017 |
|
|
} |
1018 |
|
|
} |
1019 |
|
|
|
1020 |
|
|
|
1021 |
|
|
/* |
1022 |
|
|
* Preferences may have changed |
1023 |
|
|
*/ |
1024 |
|
|
|
1025 |
|
|
void DigitalRenderer::NewPrefs(Prefs *prefs) |
1026 |
|
|
{ |
1027 |
|
|
calc_filter(); |
1028 |
|
|
} |
1029 |
|
|
|
1030 |
|
|
|
1031 |
|
|
/* |
1032 |
|
|
* Calculate IIR filter coefficients |
1033 |
|
|
*/ |
1034 |
|
|
|
1035 |
|
|
void DigitalRenderer::calc_filter(void) |
1036 |
|
|
{ |
1037 |
|
|
#ifdef USE_FIXPOINT_MATHS |
1038 |
|
|
FixPoint fr, arg; |
1039 |
|
|
|
1040 |
|
|
if (f_type == FILT_ALL) |
1041 |
|
|
{ |
1042 |
|
|
d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = FixNo(1); return; |
1043 |
|
|
} |
1044 |
|
|
else if (f_type == FILT_NONE) |
1045 |
|
|
{ |
1046 |
|
|
d1 = 0; d2 = 0; g1 = 0; g2 = 0; f_ampl = 0; return; |
1047 |
|
|
} |
1048 |
|
|
#else |
1049 |
|
|
float fr, arg; |
1050 |
|
|
|
1051 |
|
|
// Check for some trivial cases |
1052 |
|
|
if (f_type == FILT_ALL) { |
1053 |
|
|
d1 = 0.0; d2 = 0.0; |
1054 |
|
|
g1 = 0.0; g2 = 0.0; |
1055 |
|
|
f_ampl = 1.0; |
1056 |
|
|
return; |
1057 |
|
|
} else if (f_type == FILT_NONE) { |
1058 |
|
|
d1 = 0.0; d2 = 0.0; |
1059 |
|
|
g1 = 0.0; g2 = 0.0; |
1060 |
|
|
f_ampl = 0.0; |
1061 |
|
|
return; |
1062 |
|
|
} |
1063 |
|
|
#endif |
1064 |
|
|
|
1065 |
|
|
// Calculate resonance frequency |
1066 |
|
|
if (f_type == FILT_LP || f_type == FILT_LPBP) |
1067 |
|
|
#ifdef PRECOMPUTE_RESONANCE |
1068 |
|
|
fr = resonanceLP[f_freq]; |
1069 |
|
|
#else |
1070 |
|
|
fr = CALC_RESONANCE_LP(f_freq); |
1071 |
|
|
#endif |
1072 |
|
|
else |
1073 |
|
|
#ifdef PRECOMPUTE_RESONANCE |
1074 |
|
|
fr = resonanceHP[f_freq]; |
1075 |
|
|
#else |
1076 |
|
|
fr = CALC_RESONANCE_HP(f_freq); |
1077 |
|
|
#endif |
1078 |
|
|
|
1079 |
|
|
#ifdef USE_FIXPOINT_MATHS |
1080 |
|
|
// explanations see below. |
1081 |
|
|
arg = fr / (SAMPLE_FREQ >> 1); |
1082 |
|
|
if (arg > FixNo(0.99)) {arg = FixNo(0.99);} |
1083 |
|
|
if (arg < FixNo(0.01)) {arg = FixNo(0.01);} |
1084 |
|
|
|
1085 |
|
|
g2 = FixNo(0.55) + FixNo(1.2) * arg * (arg - 1) + FixNo(0.0133333333) * f_res; |
1086 |
|
|
g1 = FixNo(-2) * g2.sqrt() * fixcos(arg); |
1087 |
|
|
|
1088 |
|
|
if (f_type == FILT_LPBP || f_type == FILT_HPBP) {g2 += FixNo(0.1);} |
1089 |
|
|
|
1090 |
|
|
if (g1.abs() >= g2 + 1) |
1091 |
|
|
{ |
1092 |
|
|
if (g1 > 0) {g1 = g2 + FixNo(0.99);} |
1093 |
|
|
else {g1 = -(g2 + FixNo(0.99));} |
1094 |
|
|
} |
1095 |
|
|
|
1096 |
|
|
switch (f_type) |
1097 |
|
|
{ |
1098 |
|
|
case FILT_LPBP: |
1099 |
|
|
case FILT_LP: |
1100 |
|
|
d1 = FixNo(2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 + g1 + g2); break; |
1101 |
|
|
case FILT_HPBP: |
1102 |
|
|
case FILT_HP: |
1103 |
|
|
d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break; |
1104 |
|
|
case FILT_BP: |
1105 |
|
|
d1 = 0; d2 = FixNo(-1); |
1106 |
|
|
f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg); |
1107 |
|
|
break; |
1108 |
|
|
case FILT_NOTCH: |
1109 |
|
|
d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1); |
1110 |
|
|
f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg); |
1111 |
|
|
break; |
1112 |
|
|
default: break; |
1113 |
|
|
} |
1114 |
|
|
|
1115 |
|
|
#else |
1116 |
|
|
|
1117 |
|
|
// Limit to <1/2 sample frequency, avoid div by 0 in case FILT_BP below |
1118 |
|
|
arg = fr / (float)(SAMPLE_FREQ >> 1); |
1119 |
|
|
if (arg > 0.99) |
1120 |
|
|
arg = 0.99; |
1121 |
|
|
if (arg < 0.01) |
1122 |
|
|
arg = 0.01; |
1123 |
|
|
|
1124 |
|
|
// Calculate poles (resonance frequency and resonance) |
1125 |
|
|
g2 = 0.55 + 1.2 * arg * arg - 1.2 * arg + (float)f_res * 0.0133333333; |
1126 |
|
|
g1 = -2.0 * sqrt(g2) * cos(M_PI * arg); |
1127 |
|
|
|
1128 |
|
|
// Increase resonance if LP/HP combined with BP |
1129 |
|
|
if (f_type == FILT_LPBP || f_type == FILT_HPBP) |
1130 |
|
|
g2 += 0.1; |
1131 |
|
|
|
1132 |
|
|
// Stabilize filter |
1133 |
|
|
if (fabs(g1) >= g2 + 1.0) |
1134 |
|
|
if (g1 > 0.0) |
1135 |
|
|
g1 = g2 + 0.99; |
1136 |
|
|
else |
1137 |
|
|
g1 = -(g2 + 0.99); |
1138 |
|
|
|
1139 |
|
|
// Calculate roots (filter characteristic) and input attenuation |
1140 |
|
|
switch (f_type) { |
1141 |
|
|
|
1142 |
|
|
case FILT_LPBP: |
1143 |
|
|
case FILT_LP: |
1144 |
|
|
d1 = 2.0; d2 = 1.0; |
1145 |
|
|
f_ampl = 0.25 * (1.0 + g1 + g2); |
1146 |
|
|
break; |
1147 |
|
|
|
1148 |
|
|
case FILT_HPBP: |
1149 |
|
|
case FILT_HP: |
1150 |
|
|
d1 = -2.0; d2 = 1.0; |
1151 |
|
|
f_ampl = 0.25 * (1.0 - g1 + g2); |
1152 |
|
|
break; |
1153 |
|
|
|
1154 |
|
|
case FILT_BP: |
1155 |
|
|
d1 = 0.0; d2 = -1.0; |
1156 |
|
|
f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / sin(M_PI * arg); |
1157 |
|
|
break; |
1158 |
|
|
|
1159 |
|
|
case FILT_NOTCH: |
1160 |
|
|
d1 = -2.0 * cos(M_PI * arg); d2 = 1.0; |
1161 |
|
|
f_ampl = 0.25 * (1.0 + g1 + g2) * (1 + cos(M_PI * arg)) / (sin(M_PI * arg)); |
1162 |
|
|
break; |
1163 |
|
|
|
1164 |
|
|
default: |
1165 |
|
|
break; |
1166 |
|
|
} |
1167 |
|
|
#endif |
1168 |
|
|
} |
1169 |
|
|
|
1170 |
|
|
|
1171 |
|
|
/* |
1172 |
|
|
* Fill one audio buffer with calculated SID sound |
1173 |
|
|
*/ |
1174 |
|
|
|
1175 |
|
|
#ifdef __riscos__ |
1176 |
|
|
void DigitalRenderer::calc_buffer(uint8 *buf, long count) |
1177 |
|
|
#else |
1178 |
|
|
void DigitalRenderer::calc_buffer(int16 *buf, long count) |
1179 |
|
|
#endif |
1180 |
|
|
{ |
1181 |
|
|
// Get filter coefficients, so the emulator won't change |
1182 |
|
|
// them in the middle of our calculations |
1183 |
|
|
#ifdef USE_FIXPOINT_MATHS |
1184 |
|
|
FixPoint cf_ampl = f_ampl; |
1185 |
|
|
FixPoint cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2; |
1186 |
|
|
#else |
1187 |
|
|
float cf_ampl = f_ampl; |
1188 |
|
|
float cd1 = d1, cd2 = d2, cg1 = g1, cg2 = g2; |
1189 |
|
|
#endif |
1190 |
|
|
|
1191 |
|
|
#ifdef __riscos__ |
1192 |
|
|
uint8 *LinToLog, *LogScale; |
1193 |
|
|
#endif |
1194 |
|
|
|
1195 |
|
|
// Index in sample_buf for reading, 16.16 fixed |
1196 |
|
|
uint32 sample_count = (sample_in_ptr + SAMPLE_BUF_SIZE/2) << 16; |
1197 |
|
|
|
1198 |
|
|
#ifdef __riscos__ // on RISC OS we have 8 bit logarithmic sound |
1199 |
|
|
DigitalRenderer_GetTables(&LinToLog, &LogScale); // get translation tables |
1200 |
|
|
#else |
1201 |
|
|
count >>= 1; // 16 bit mono output, count is in bytes |
1202 |
|
|
#endif |
1203 |
|
|
while (count--) { |
1204 |
|
|
int32 sum_output; |
1205 |
|
|
int32 sum_output_filter = 0; |
1206 |
|
|
|
1207 |
|
|
// Get current master volume from sample buffer, |
1208 |
|
|
// calculate sampled voice |
1209 |
|
|
uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE]; |
1210 |
|
|
sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ; |
1211 |
|
|
sum_output = SampleTab[master_volume] << 8; |
1212 |
|
|
|
1213 |
|
|
// Loop for all three voices |
1214 |
|
|
for (int j=0; j<3; j++) { |
1215 |
|
|
DRVoice *v = &voice[j]; |
1216 |
|
|
|
1217 |
|
|
// Envelope generators |
1218 |
|
|
uint16 envelope; |
1219 |
|
|
|
1220 |
|
|
switch (v->eg_state) { |
1221 |
|
|
case EG_ATTACK: |
1222 |
|
|
v->eg_level += v->a_add; |
1223 |
|
|
if (v->eg_level > 0xffffff) { |
1224 |
|
|
v->eg_level = 0xffffff; |
1225 |
|
|
v->eg_state = EG_DECAY; |
1226 |
|
|
} |
1227 |
|
|
break; |
1228 |
|
|
case EG_DECAY: |
1229 |
|
|
if (v->eg_level <= v->s_level || v->eg_level > 0xffffff) |
1230 |
|
|
v->eg_level = v->s_level; |
1231 |
|
|
else { |
1232 |
|
|
v->eg_level -= v->d_sub >> EGDRShift[v->eg_level >> 16]; |
1233 |
|
|
if (v->eg_level <= v->s_level || v->eg_level > 0xffffff) |
1234 |
|
|
v->eg_level = v->s_level; |
1235 |
|
|
} |
1236 |
|
|
break; |
1237 |
|
|
case EG_RELEASE: |
1238 |
|
|
v->eg_level -= v->r_sub >> EGDRShift[v->eg_level >> 16]; |
1239 |
|
|
if (v->eg_level > 0xffffff) { |
1240 |
|
|
v->eg_level = 0; |
1241 |
|
|
v->eg_state = EG_IDLE; |
1242 |
|
|
} |
1243 |
|
|
break; |
1244 |
|
|
case EG_IDLE: |
1245 |
|
|
v->eg_level = 0; |
1246 |
|
|
break; |
1247 |
|
|
} |
1248 |
|
|
envelope = (v->eg_level * master_volume) >> 20; |
1249 |
|
|
|
1250 |
|
|
// Waveform generator |
1251 |
cebix |
1.3 |
if (v->mute) |
1252 |
|
|
continue; |
1253 |
cebix |
1.1 |
uint16 output; |
1254 |
|
|
|
1255 |
|
|
if (!v->test) |
1256 |
|
|
v->count += v->add; |
1257 |
|
|
|
1258 |
|
|
if (v->sync && (v->count > 0x1000000)) |
1259 |
|
|
v->mod_to->count = 0; |
1260 |
|
|
|
1261 |
|
|
v->count &= 0xffffff; |
1262 |
|
|
|
1263 |
|
|
switch (v->wave) { |
1264 |
|
|
case WAVE_TRI: |
1265 |
|
|
if (v->ring) |
1266 |
|
|
output = TriTable[(v->count ^ (v->mod_by->count & 0x800000)) >> 11]; |
1267 |
|
|
else |
1268 |
|
|
output = TriTable[v->count >> 11]; |
1269 |
|
|
break; |
1270 |
|
|
case WAVE_SAW: |
1271 |
|
|
output = v->count >> 8; |
1272 |
|
|
break; |
1273 |
|
|
case WAVE_RECT: |
1274 |
|
|
if (v->count > (uint32)(v->pw << 12)) |
1275 |
|
|
output = 0xffff; |
1276 |
|
|
else |
1277 |
|
|
output = 0; |
1278 |
|
|
break; |
1279 |
|
|
case WAVE_TRISAW: |
1280 |
|
|
output = TriSawTable[v->count >> 16]; |
1281 |
|
|
break; |
1282 |
|
|
case WAVE_TRIRECT: |
1283 |
|
|
if (v->count > (uint32)(v->pw << 12)) |
1284 |
|
|
output = TriRectTable[v->count >> 16]; |
1285 |
|
|
else |
1286 |
|
|
output = 0; |
1287 |
|
|
break; |
1288 |
|
|
case WAVE_SAWRECT: |
1289 |
|
|
if (v->count > (uint32)(v->pw << 12)) |
1290 |
|
|
output = SawRectTable[v->count >> 16]; |
1291 |
|
|
else |
1292 |
|
|
output = 0; |
1293 |
|
|
break; |
1294 |
|
|
case WAVE_TRISAWRECT: |
1295 |
|
|
if (v->count > (uint32)(v->pw << 12)) |
1296 |
|
|
output = TriSawRectTable[v->count >> 16]; |
1297 |
|
|
else |
1298 |
|
|
output = 0; |
1299 |
|
|
break; |
1300 |
|
|
case WAVE_NOISE: |
1301 |
|
|
if (v->count > 0x100000) { |
1302 |
|
|
output = v->noise = sid_random() << 8; |
1303 |
|
|
v->count &= 0xfffff; |
1304 |
|
|
} else |
1305 |
|
|
output = v->noise; |
1306 |
|
|
break; |
1307 |
|
|
default: |
1308 |
|
|
output = 0x8000; |
1309 |
|
|
break; |
1310 |
|
|
} |
1311 |
|
|
if (v->filter) |
1312 |
|
|
sum_output_filter += (int16)(output ^ 0x8000) * envelope; |
1313 |
|
|
else |
1314 |
|
|
sum_output += (int16)(output ^ 0x8000) * envelope; |
1315 |
|
|
} |
1316 |
|
|
|
1317 |
|
|
// Filter |
1318 |
|
|
if (ThePrefs.SIDFilters) { |
1319 |
|
|
#ifdef USE_FIXPOINT_MATHS |
1320 |
|
|
int32 xn = cf_ampl.imul(sum_output_filter); |
1321 |
|
|
int32 yn = xn+cd1.imul(xn1)+cd2.imul(xn2)-cg1.imul(yn1)-cg2.imul(yn2); |
1322 |
|
|
yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn; |
1323 |
|
|
sum_output_filter = yn; |
1324 |
|
|
#else |
1325 |
|
|
float xn = (float)sum_output_filter * cf_ampl; |
1326 |
|
|
float yn = xn + cd1 * xn1 + cd2 * xn2 - cg1 * yn1 - cg2 * yn2; |
1327 |
|
|
yn2 = yn1; yn1 = yn; xn2 = xn1; xn1 = xn; |
1328 |
|
|
sum_output_filter = (int32)yn; |
1329 |
|
|
#endif |
1330 |
|
|
} |
1331 |
|
|
|
1332 |
|
|
// Write to buffer |
1333 |
cebix |
1.4 |
#if defined(__riscos__) // lookup in 8k (13bit) translation table |
1334 |
cebix |
1.1 |
*buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff]; |
1335 |
|
|
#else |
1336 |
|
|
*buf++ = (sum_output + sum_output_filter) >> 10; |
1337 |
|
|
#endif |
1338 |
|
|
} |
1339 |
|
|
} |
1340 |
|
|
|
1341 |
|
|
|
1342 |
|
|
// Manufacturer independent sound is still just a dream... |
1343 |
|
|
#if defined(__BEOS__) |
1344 |
|
|
#include "SID_Be.h" |
1345 |
|
|
|
1346 |
|
|
#elif defined(AMIGA) |
1347 |
|
|
#include "SID_Amiga.h" |
1348 |
|
|
|
1349 |
|
|
#elif defined(__linux__) |
1350 |
|
|
#include "SID_linux.h" |
1351 |
|
|
|
1352 |
|
|
#elif defined(SUN) |
1353 |
|
|
#include "SID_sun.h" |
1354 |
|
|
|
1355 |
|
|
#elif defined(__hpux) |
1356 |
|
|
#include "SID_hp.h" |
1357 |
|
|
|
1358 |
|
|
#elif defined(__mac__) |
1359 |
|
|
#include "SID_mac.h" |
1360 |
|
|
|
1361 |
|
|
#elif defined(WIN32) |
1362 |
|
|
#include "SID_WIN32.h" |
1363 |
|
|
|
1364 |
|
|
#elif defined(__riscos__) |
1365 |
|
|
#include "SID_Acorn.h" |
1366 |
|
|
|
1367 |
|
|
#else // No sound |
1368 |
|
|
void DigitalRenderer::init_sound(void) {ready = false;} |
1369 |
|
|
DigitalRenderer::~DigitalRenderer() {} |
1370 |
|
|
void DigitalRenderer::EmulateLine(void) {} |
1371 |
|
|
void DigitalRenderer::Pause(void) {} |
1372 |
|
|
void DigitalRenderer::Resume(void) {} |
1373 |
|
|
#endif |
1374 |
|
|
|
1375 |
|
|
|
1376 |
|
|
/* |
1377 |
|
|
* Open/close the renderer, according to old and new prefs |
1378 |
|
|
*/ |
1379 |
|
|
|
1380 |
|
|
void MOS6581::open_close_renderer(int old_type, int new_type) |
1381 |
|
|
{ |
1382 |
|
|
if (old_type == new_type) |
1383 |
|
|
return; |
1384 |
|
|
|
1385 |
|
|
// Delete the old renderer |
1386 |
|
|
delete the_renderer; |
1387 |
|
|
|
1388 |
|
|
// Create new renderer |
1389 |
|
|
if (new_type == SIDTYPE_DIGITAL) |
1390 |
|
|
#if defined(__BEOS__) || defined(__riscos__) |
1391 |
|
|
the_renderer = new DigitalRenderer(the_c64); |
1392 |
|
|
#else |
1393 |
|
|
the_renderer = new DigitalRenderer(); |
1394 |
|
|
#endif |
1395 |
|
|
#ifdef AMIGA |
1396 |
|
|
else if (new_type == SIDTYPE_SIDCARD) |
1397 |
|
|
the_renderer = new SIDCardRenderer(); |
1398 |
|
|
#endif |
1399 |
cebix |
1.5 |
#ifdef __linux__ |
1400 |
|
|
else if (new_type == SIDTYPE_SIDCARD) |
1401 |
|
|
the_renderer = new CatweaselRenderer(); |
1402 |
|
|
#endif |
1403 |
cebix |
1.1 |
else |
1404 |
|
|
the_renderer = NULL; |
1405 |
|
|
|
1406 |
|
|
// Stuff the current register values into the new renderer |
1407 |
|
|
if (the_renderer != NULL) |
1408 |
|
|
for (int i=0; i<25; i++) |
1409 |
|
|
the_renderer->WriteRegister(i, regs[i]); |
1410 |
|
|
} |