8 extern Event evenv, evwave;
9 s16int sbuf[2*4000], *sbufp;
12 SRATEDIV = FREQ / Freq
17 u8int sweepen, sweepcalc, sweepctr;
19 typedef struct chan chan;
56 VAR(apustatus), VAR(envmod), VAR(sweepen), VAR(sweepcalc),
57 VAR(sweepctr), VAR(sweepfreq), VAR(wpos), VAR(lfsr), VAR(waveclock), VAR(wavebuf),
58 VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].fctr), VAR(sndch[0].fthr), VAR(sndch[0].finc), VAR(sndch[0].vol),
59 VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].fctr), VAR(sndch[1].fthr), VAR(sndch[1].finc), VAR(sndch[1].vol),
60 VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].fctr), VAR(sndch[2].fthr), VAR(sndch[2].finc), VAR(sndch[2].vol),
61 VAR(sndch[3].ectr), VAR(sndch[3].len), VAR(sndch[3].fctr), VAR(sndch[3].fthr), VAR(sndch[3].finc), VAR(sndch[3].vol),
70 sndch[i].finc = 131072ULL * 65536 / (Freq * (2048 - (v & 0x7ff)));
73 sndch[2].finc = 4 * (2048 - (v & 0x7ff));
76 sndch[3].finc = 524288ULL * 65536 / Freq;
78 sndch[3].finc /= v & 7;
81 sndch[3].finc >>= (v >> 4 & 15) + 1;
88 if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<6) != 0)
90 apustatus &= ~(1<<c->n);
94 if((apustatus & 1<<c->n) == 0 || (envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
96 c->ectr = *c->env & 7;
97 if((*c->env & 1<<3) != 0){
108 addevent(&evwave, sndch[2].finc);
109 wpos = wpos + 1 & 31;
110 wavebuf = reg[WAVE + (wpos >> 1)];
119 if((apustatus & 1<<4) == 0)
126 if((reg[NR32] & 3<<5) == 0)
129 x = x >> (reg[NR32] >> 5 & 3) - 1;
139 sndch[3].fctr = v = sndch[3].fctr + sndch[3].finc;
146 if(((l ^ lfsr) & 1) != 0)
147 if((reg[NR43] & 1<<3) != 0)
166 d = sweepfreq >> (cnt & 7);
167 if((cnt & 1<<3) != 0)
176 }else if(wb && (cnt & 7) != 0){
179 reg[NR14] = reg[NR14] & 0xf8 | fr >> 8;
186 sndstart(chan *c, u8int v)
190 c->vol = *c->env >> 4;
191 c->ectr = *c->env & 7;
194 apustatus |= 1<<c->n;
197 sweepen = (cnt & 0x07) != 0 || (cnt & 0x70) != 0;
198 sweepctr = cnt >> 4 & 7;
199 sweepctr += sweepctr - 1 & 8;
200 sweepfreq = v << 8 & 0x700 | reg[NR13];
202 if((cnt & 0x07) != 0)
205 if((*c->freq & 0x40) == 0 && (v & 0x40) != 0 && (envmod & 1) != 0 && --c->len == 0 || (*c->env & 0xf8) == 0){
206 apustatus &= ~(1<<c->n);
214 addevent(&evenv, FREQ / 512);
218 if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[NR34] & 0x40) != 0)
219 if(--sndch[2].len == 0){
224 if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
225 sweepctr = reg[NR10] >> 4 & 7;
226 sweepctr += sweepctr - 1 & 8;
227 if((reg[NR10] & 0x70) != 0)
241 addevent(&evsamp, SRATEDIV);
243 sndch[0].fctr += sndch[0].finc;
244 if(sndch[0].fctr >= sndch[0].fthr)
245 ch[0] = sndch[0].vol;
248 sndch[1].fctr += sndch[1].finc;
249 if(sndch[1].fctr >= sndch[1].fthr)
250 ch[1] = sndch[1].vol;
260 for(i = 0; i < 4; i++){
261 if(i == 2 ? ((reg[NR30] & 0x80) == 0) : ((*sndch[i].env & 0xf8) == 0))
263 ch[i] = ch[i] * 2 - 15;
264 if((cnth & 1<<i) != 0)
266 if((cnth & 1<<4<<i) != 0)
269 s[0] *= 1 + (cntl & 7);
270 s[1] *= 1 + (cntl >> 4 & 7);
272 if(sbufp < sbuf + nelem(sbuf)){
273 sbufp[0] = s[0] * 30;
274 sbufp[1] = s[1] * 30;
280 sndwrite(u8int a, u8int v)
282 static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
283 static u8int clrreg[] = {
284 0x80, 0x3f, 0x00, 0xff, 0xbf,
285 0xff, 0x3f, 0x00, 0xff, 0xbf,
286 0x7f, 0xff, 0x9f, 0xff, 0xbf,
287 0xff, 0xff, 0x00, 0x00, 0xbf,
291 if((reg[NR52] & 0x80) == 0 && a != NR52 && ((mode & CGB) != 0 || a != NR11 && a != NR21 && a != NR31 && a != NR41))
295 if((sweepcalc & 0x08) != 0 && (reg[NR10] & ~v & 0x08) != 0){
302 sndch[0].fthr = thr[v >> 6 & 3];
303 sndch[0].len = 64 - (v & 63);
312 rate(0, reg[NR14] << 8 & 0x700 | v);
315 rate(0, v << 8 & 0x700 | reg[NR13]);
317 sndstart(&sndch[0], v);
320 sndch[1].fthr = thr[v >> 6 & 3];
321 sndch[1].len = 64 - (v & 63);
330 rate(1, reg[NR24] << 8 & 0x700 | v);
333 rate(1, v << 8 & 0x700 | reg[NR23]);
335 sndstart(&sndch[1], v);
344 sndch[2].len = 256 - (v & 0xff);
347 rate(2, reg[NR34] << 8 & 0x700 | v);
350 rate(2, v << 8 & 0x700 | reg[NR33]);
352 if(sndch[2].len == 0)
355 if((reg[NR30] & 0x80) != 0){
358 addevent(&evwave, sndch[2].finc);
363 sndch[3].len = 64 - (v & 63);
376 if((reg[NR43] & 1<<3) != 0)
380 sndstart(&sndch[3], v);
384 apustatus = v & 0xf0 | apustatus & 0x0f;
386 memcpy(reg + NR10, clrreg, NR52 - NR10);
387 if((mode & CGB) != 0){
395 }else if((reg[NR52] & 0x80) == 0){
398 addevent(&evenv, FREQ / 512);
410 if((apustatus & 4) != 0)
411 if((mode & CGB) != 0 || clock - waveclock == 0)
415 return reg[WAVE + a];
419 wavewrite(u8int a, u8int v)
427 fd = open("/dev/audio", OWRITE);
429 sysfatal("open: %r");
431 evsamp.f = sampletick;
432 addevent(&evsamp, SRATEDIV);
446 rc = write(fd, sbuf, (sbufp - sbuf) * 2);