12 s16int sbuf[2*4000], *sbufp;
15 SRATEDIV = FREQ / Freq
20 u8int sweepen, sweepcalc, sweepctr;
22 typedef struct chan chan;
68 VAR(apustatus), VAR(envmod), VAR(sweepen), VAR(sweepcalc),
69 VAR(sweepctr), VAR(sweepfreq), VAR(wpos), VAR(lfsr), VAR(waveclock), VAR(wavebuf),
70 VAR(sndch[0].ectr), VAR(sndch[0].len), VAR(sndch[0].per), VAR(sndch[0].ctr), VAR(sndch[0].vol), VAR(sndch[0].samp),
71 VAR(sndch[1].ectr), VAR(sndch[1].len), VAR(sndch[1].per), VAR(sndch[1].ctr), VAR(sndch[1].vol), VAR(sndch[1].samp),
72 VAR(sndch[2].ectr), VAR(sndch[2].len), VAR(sndch[2].per), VAR(sndch[2].vol), VAR(sndch[2].samp),
73 VAR(sndch[3].ectr), VAR(sndch[3].len), VAR(sndch[3].per), VAR(sndch[3].vol), VAR(sndch[3].samp),
78 rate(chan *c, u16int v)
82 c->per = 8 * (2048 - (v & 0x7ff));
85 c->per = 4 * (2048 - (v & 0x7ff));
93 c->per <<= (v >> 4 & 15);
101 static u32int oclock;
106 e = exp((clock + t - oclock) * -(TAU / FREQ));
107 samp[0] = e * samp[0] + (1 - e) * ov0;
108 samp[1] = e * samp[1] + (1 - e) * ov1;
114 for(i = 0; i < 4; i++){
115 if(i == 2 ? ((reg[NR30] & 0x80) == 0) : ((*sndch[i].env & 0xf8) == 0))
117 v = sndch[i].samp * 2 - 15;
118 if((cnth & 1<<i) != 0)
120 if((cnth & 1<<4<<i) != 0)
123 ov0 *= 1 + (cntl & 7);
124 ov1 *= 1 + (cntl >> 4 & 7);
128 chansamp(chan *c, int t)
136 switch(reg[NR21] >> 6){
137 case 0: if(c->ctr < 7) c->samp = 0; break;
138 case 1: if(c->ctr < 6) c->samp = 0; break;
139 case 2: if(c->ctr < 4) c->samp = 0; break;
140 case 3: if(c->ctr >= 6) c->samp = 0; break;
144 if((apustatus & 1<<4) == 0){
153 if((reg[NR32] & 3<<5) == 0)
156 c->samp = c->samp >> (reg[NR32] >> 5 & 3) - 1;
159 c->samp = (lfsr & 1) != 0 ? 0 : c->vol;
174 c->ctr = c->ctr - 1 & 7;
177 wpos = wpos + 1 & 31;
178 wavebuf = reg[WAVE + (wpos >> 1)];
184 if(((l ^ lfsr) & 1) != 0)
185 if((reg[NR43] & 1<<3) != 0)
191 chansamp(c, chev[c->n].time);
192 addevent(&chev[c->n], c->per);
198 if((envmod & 1) == 0 && c->len > 0 && (*c->freq & 1<<6) != 0)
200 apustatus &= ~(1<<c->n);
205 if((apustatus & 1<<c->n) == 0 || (envmod & 7) != 7 || c->ectr == 0 || --c->ectr != 0)
207 c->ectr = *c->env & 7;
208 if((*c->env & 1<<3) != 0){
228 d = sweepfreq >> (cnt & 7);
229 if((cnt & 1<<3) != 0)
236 chansamp(&sndch[0], t);
239 }else if(wb && (cnt & 7) != 0){
242 reg[NR14] = reg[NR14] & 0xf8 | fr >> 8;
249 sndstart(chan *c, u8int v)
254 c->vol = *c->env >> 4;
255 c->ectr = *c->env & 7;
258 apustatus |= 1<<c->n;
261 sweepen = (cnt & 0x07) != 0 || (cnt & 0x70) != 0;
262 sweepctr = cnt >> 4 & 7;
263 sweepctr += sweepctr - 1 & 8;
264 sweepfreq = v << 8 & 0x700 | reg[NR13];
266 if((cnt & 0x07) != 0)
269 if((*c->freq & 0x40) == 0 && (v & 0x40) != 0 && (envmod & 1) != 0 && --c->len == 0 || (*c->env & 0xf8) == 0){
270 apustatus &= ~(1<<c->n);
279 env(&sndch[0], evenv.time);
280 env(&sndch[1], evenv.time);
281 if((envmod & 1) == 0 && sndch[2].len > 0 && (reg[NR34] & 0x40) != 0)
282 if(--sndch[2].len == 0){
286 env(&sndch[3], evenv.time);
287 if((envmod & 3) == 2 && sweepen && --sweepctr == 0){
288 sweepctr = reg[NR10] >> 4 & 7;
289 sweepctr += sweepctr - 1 & 8;
290 if((reg[NR10] & 0x70) != 0)
291 sweep(1, evenv.time);
294 addevent(&evenv, FREQ / 512);
301 if(sbufp < sbuf + nelem(sbuf)){
302 sbufp[0] = samp[0] * 30;
303 sbufp[1] = samp[1] * 30;
306 addevent(&evsamp, SRATEDIV);
310 sndwrite(u8int a, u8int v)
312 static u16int thr[4] = {0x2000, 0x4000, 0x8000, 0xC000};
313 static u8int clrreg[] = {
314 0x80, 0x3f, 0x00, 0xff, 0xbf,
315 0xff, 0x3f, 0x00, 0xff, 0xbf,
316 0x7f, 0xff, 0x9f, 0xff, 0xbf,
317 0xff, 0xff, 0x00, 0x00, 0xbf,
321 if((reg[NR52] & 0x80) == 0 && a != NR52 && ((mode & CGB) != 0 || a != NR11 && a != NR21 && a != NR31 && a != NR41))
325 if((sweepcalc & 0x08) != 0 && (reg[NR10] & ~v & 0x08) != 0){
332 sndch[0].len = 64 - (v & 63);
341 rate(&sndch[0], reg[NR14] << 8 & 0x700 | v);
344 rate(&sndch[0], v << 8 & 0x700 | reg[NR13]);
346 sndstart(&sndch[0], v);
349 sndch[1].len = 64 - (v & 63);
358 rate(&sndch[1], reg[NR24] << 8 & 0x700 | v);
361 rate(&sndch[1], v << 8 & 0x700 | reg[NR23]);
363 sndstart(&sndch[1], v);
372 sndch[2].len = 256 - (v & 0xff);
375 rate(&sndch[2], reg[NR34] << 8 & 0x700 | v);
378 rate(&sndch[2], v << 8 & 0x700 | reg[NR33]);
380 if(sndch[2].len == 0)
383 if((reg[NR30] & 0x80) != 0){
386 addevent(&chev[2], sndch[2].per);
391 sndch[3].len = 64 - (v & 63);
404 if((reg[NR43] & 1<<3) != 0)
408 sndstart(&sndch[3], v);
411 case NR50: case NR51:
415 apustatus = v & 0xf0 | apustatus & 0x0f;
417 memcpy(reg + NR10, clrreg, NR52 - NR10);
418 if((mode & CGB) != 0){
426 }else if((reg[NR52] & 0x80) == 0){
429 addevent(&evenv, FREQ / 512);
440 if((apustatus & 4) != 0)
441 if((mode & CGB) != 0 || clock - waveclock == 0)
445 return reg[WAVE + a];
449 wavewrite(u8int a, u8int v)
457 fd = open("/dev/audio", OWRITE);
459 sysfatal("open: %r");
461 evsamp.f = sampletick;
462 addevent(&evsamp, SRATEDIV);
463 addevent(&chev[0], 8 * 2048);
464 addevent(&chev[1], 8 * 2048);
465 addevent(&chev[3], 8 * 2048);
479 rc = warp10 ? (sbufp - sbuf) * 2 : write(fd, sbuf, (sbufp - sbuf) * 2);