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