1 /*
2 * GOATTRACKER reSID interface
3 */
4
5 #define GSID_C
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include "resid/sid.h"
10 #include "resid-fp/sidfp.h"
11
12 #include "gsid.h"
13 #include "gsound.h"
14
15 int clockrate;
16 int samplerate;
17 unsigned char sidreg[NUMSIDREGS];
18 unsigned char sidorder[] =
19 {0x18,0x17,0x16,0x15,
20 0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,
21 0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,
22 0x06,0x05,0x04,0x03,0x02,0x01,0x00};
23
24 unsigned char altsidorder[] =
25 {0x00,0x01,0x02,0x03,0x04,0x05,0x06,
26 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,
27 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
28 0x15,0x16,0x17,0x18};
29
30 SID *sid = 0;
31 SIDFP *sidfp = 0;
32
33 FILTERPARAMS filterparams =
34 {0.50f, 3.3e6f, 1.0e-4f,
35 1147036.4394268463f, 274228796.97550374f, 1.0066634233403395f, 16125.154840564108f,
36 5.5f, 20.f,
37 0.9613160610660189f};
38
39 extern unsigned residdelay;
40 extern unsigned adparam;
41
sid_init(int speed,unsigned m,unsigned ntsc,unsigned interpolate,unsigned customclockrate,unsigned usefp)42 void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate, unsigned usefp)
43 {
44 int c;
45
46 if (ntsc) clockrate = NTSCCLOCKRATE;
47 else clockrate = PALCLOCKRATE;
48
49 if (customclockrate)
50 clockrate = customclockrate;
51
52 samplerate = speed;
53
54 if (!usefp)
55 {
56 if (sidfp)
57 {
58 delete sidfp;
59 sidfp = NULL;
60 }
61
62 if (!sid) sid = new SID;
63 }
64 else
65 {
66 if (sid)
67 {
68 delete sid;
69 sid = NULL;
70 }
71
72 if (!sidfp) sidfp = new SIDFP;
73 }
74
75 switch(interpolate)
76 {
77 case 0:
78 if (sid) sid->set_sampling_parameters(clockrate, SAMPLE_FAST, speed);
79 if (sidfp) sidfp->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed);
80 break;
81
82 default:
83 if (sid) sid->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed);
84 if (sidfp) sidfp->set_sampling_parameters(clockrate, SAMPLE_RESAMPLE_INTERPOLATE, speed);
85 break;
86 }
87
88 if (sid) sid->reset();
89 if (sidfp) sidfp->reset();
90 for (c = 0; c < NUMSIDREGS; c++)
91 {
92 sidreg[c] = 0x00;
93 }
94 if (m == 1)
95 {
96 if (sid) sid->set_chip_model(MOS8580);
97 if (sidfp) sidfp->set_chip_model(MOS8580);
98 }
99 else
100 {
101 if (sid) sid->set_chip_model(MOS6581);
102 if (sidfp) sidfp->set_chip_model(MOS6581);
103 }
104
105 if (sidfp)
106 {
107 sidfp->get_filter().set_distortion_properties(
108 filterparams.distortionrate,
109 filterparams.distortionpoint,
110 filterparams.distortioncfthreshold);
111 sidfp->get_filter().set_type3_properties(
112 filterparams.type3baseresistance,
113 filterparams.type3offset,
114 filterparams.type3steepness,
115 filterparams.type3minimumfetresistance);
116 sidfp->get_filter().set_type4_properties(
117 filterparams.type4k,
118 filterparams.type4b);
119 sidfp->set_voice_nonlinearity(
120 filterparams.voicenonlinearity);
121 }
122 }
123
sid_getorder(unsigned char index)124 unsigned char sid_getorder(unsigned char index)
125 {
126 if (adparam >= 0xf000)
127 return altsidorder[index];
128 else
129 return sidorder[index];
130 }
131
sid_fillbuffer(short * ptr,int samples)132 int sid_fillbuffer(short *ptr, int samples)
133 {
134 int tdelta;
135 int tdelta2;
136 int result = 0;
137 int total = 0;
138 int c;
139
140 int badline = rand() % NUMSIDREGS;
141
142 tdelta = clockrate * samples / samplerate;
143 if (tdelta <= 0) return total;
144
145 for (c = 0; c < NUMSIDREGS; c++)
146 {
147 unsigned char o = sid_getorder(c);
148
149 // Possible random badline delay once per writing
150 if ((badline == c) && (residdelay))
151 {
152 tdelta2 = residdelay;
153 if (sid) result = sid->clock(tdelta2, ptr, samples);
154 if (sidfp) result = sidfp->clock(tdelta2, ptr, samples);
155 total += result;
156 ptr += result;
157 samples -= result;
158 tdelta -= residdelay;
159 }
160
161 if (sid) sid->write(o, sidreg[o]);
162 if (sidfp) sidfp->write(o, sidreg[o]);
163
164 tdelta2 = SIDWRITEDELAY;
165 if (sid) result = sid->clock(tdelta2, ptr, samples);
166 if (sidfp) result = sidfp->clock(tdelta2, ptr, samples);
167 total += result;
168 ptr += result;
169 samples -= result;
170 tdelta -= SIDWRITEDELAY;
171
172 if (tdelta <= 0) return total;
173 }
174
175 if (sid) result = sid->clock(tdelta, ptr, samples);
176 if (sidfp) result = sidfp->clock(tdelta, ptr, samples);
177 total += result;
178 ptr += result;
179 samples -= result;
180
181 // Loop extra cycles until all samples produced
182 while (samples)
183 {
184 tdelta = clockrate * samples / samplerate;
185 if (tdelta <= 0) return total;
186
187 if (sid) result = sid->clock(tdelta, ptr, samples);
188 if (sidfp) result = sidfp->clock(tdelta, ptr, samples);
189 total += result;
190 ptr += result;
191 samples -= result;
192 }
193
194 return total;
195 }
196
197