#include #include "sfx.h" #include "hUGEDriver.h" // Stream: frame = {skip<<4 | groups}, group = {regmask<<3 | target}, values... // regmask bits 7..3 select NRx0..NRx4; target 0-3 = channel, 4 = NR50/NR51, // 5 = 16 bytes of wave RAM, 7 = end. The converters never set bits for // registers that don't exist (CH2/CH4 NRx0) or for NR52. static const uint8_t *sfx_pos; // 0 = idle static uint8_t sfx_skip; // frames to wait before the next one static uint8_t sfx_mask; // channels borrowed from the music (bit n = channel n) static uint8_t sfx_prio; #define REG(bit, reg) if (m & (bit)) reg = *p++ // Apply a mute state to every channel in sfx_mask. Muting cuts the note and // makes the driver ignore the channel until it is unmuted. static void sfx_mute(enum hUGE_mute_t mute) { uint8_t mask = sfx_mask; for (uint8_t ch = 0; mask; ch++, mask >>= 1) if (mask & 1) hUGE_mute_channel(ch, mute); } static void sfx_silence(void) { sfx_pos = 0; uint8_t mask = sfx_mask; if (mask & 0x01) NR12_REG = 0x00, NR14_REG = 0x80; // trigger with DAC off = silence if (mask & 0x02) NR22_REG = 0x00, NR24_REG = 0x80; if (mask & 0x04) NR32_REG = 0x00, hUGE_reset_wave(); // driver must reload its wave if (mask & 0x08) NR42_REG = 0x00, NR44_REG = 0x80; NR51_REG = 0xFF; sfx_mute(HT_CH_PLAY); } void sfx_stop(void) { __critical { if (sfx_pos) sfx_silence(); } } void sfx_play(const uint8_t *data) { __critical { // sfx_update runs in the VBlank interrupt (and no return in here: it would skip the ei) if (!sfx_pos || sfx_prio <= data[1]) { if (sfx_pos) sfx_silence(); sfx_mask = data[0]; sfx_prio = data[1]; sfx_skip = 0; sfx_pos = data + 2; sfx_mute(HT_CH_MUTE); } } } void sfx_update(void) { const uint8_t *p = sfx_pos; if (!p) return; if (sfx_skip) { sfx_skip--; return; } uint8_t n = *p++; sfx_skip = n >> 4; for (n &= 0x0F; n; n--) { uint8_t m = *p++; uint8_t t = m & 0x07; if (t == 0) { REG(0x80, NR10_REG); REG(0x40, NR11_REG); REG(0x20, NR12_REG); REG(0x10, NR13_REG); REG(0x08, NR14_REG); } else if (t == 1) { REG(0x40, NR21_REG); REG(0x20, NR22_REG); REG(0x10, NR23_REG); REG(0x08, NR24_REG); } else if (t == 2) { REG(0x80, NR30_REG); REG(0x40, NR31_REG); REG(0x20, NR32_REG); REG(0x10, NR33_REG); REG(0x08, NR34_REG); } else if (t == 3) { REG(0x40, NR41_REG); REG(0x20, NR42_REG); REG(0x10, NR43_REG); REG(0x08, NR44_REG); } else if (t == 4) { REG(0x80, NR50_REG); REG(0x40, NR51_REG); } else if (t == 5) { NR30_REG = 0x00; // wave RAM is only safely writable with the DAC off uint8_t *w = AUD3WAVE; for (m = 16; m; m--) *w++ = *p++; } else { sfx_silence(); return; } } sfx_pos = p; }