diff --git a/src/engine/platform/sid3.cpp b/src/engine/platform/sid3.cpp index baa9cd1e9..420b71b2e 100644 --- a/src/engine/platform/sid3.cpp +++ b/src/engine/platform/sid3.cpp @@ -107,6 +107,19 @@ void DivPlatformSID3::updateFilter(int channel) //rWrite(0x17 + 3 * channel,chan[channel].filtRes); } +void DivPlatformSID3::updateFreq(int channel) +{ + rWrite(10 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 16) & 0xff); + rWrite(11 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 8) & 0xff); + rWrite(12 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].freq & 0xff); +} + +void DivPlatformSID3::updateDuty(int channel) +{ + rWrite(7 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].duty >> 8) & 0xff); + rWrite(8 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].duty & 0xff); +} + void DivPlatformSID3::tick(bool sysTick) { for (int i=0; icalcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,8,chan[i].pitch2,chipClock,CHIP_FREQBASE); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE * 64); //if (chan[i].freq<0) chan[i].freq=0; //if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff; if (chan[i].keyOn) { rWrite(i*SID3_REGISTERS_PER_CHANNEL,SID3_CHAN_ENABLE_GATE); + rWrite(6 + i*SID3_REGISTERS_PER_CHANNEL,SID3_WAVE_PULSE); + + chan[i].duty = 0x1000; + updateDuty(i); } if (chan[i].keyOff) { @@ -129,7 +146,9 @@ void DivPlatformSID3::tick(bool sysTick) } if (chan[i].freq<0) chan[i].freq=0; - if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff; + if (chan[i].freq>0xffffff) chan[i].freq=0xffffff; + + updateFreq(i); //rWrite(i*7,chan[i].freq&0xff); //rWrite(i*7+1,chan[i].freq>>8); diff --git a/src/engine/platform/sid3.h b/src/engine/platform/sid3.h index f02e8d4b5..60be1ecb4 100644 --- a/src/engine/platform/sid3.h +++ b/src/engine/platform/sid3.h @@ -81,6 +81,8 @@ class DivPlatformSID3: public DivDispatch { friend void putDispatchChan(void*,int,int); void updateFilter(int channel); + void updateFreq(int channel); + void updateDuty(int channel); public: void acquire(short** buf, size_t len); int dispatch(DivCommand c); diff --git a/src/engine/platform/sound/sid3.c b/src/engine/platform/sound/sid3.c index f561b16be..869d3697a 100644 --- a/src/engine/platform/sound/sid3.c +++ b/src/engine/platform/sound/sid3.c @@ -159,6 +159,8 @@ SID3* sid3_create() { SID3* sid3 = (SID3*)malloc(sizeof(SID3)); + memset(sid3, 0, sizeof(SID3)); + for(int i = 0; i < SID3_NUM_SPECIAL_WAVES; i++) { for(int j = 0; j < SID3_SPECIAL_WAVE_LENGTH; j++) @@ -182,7 +184,8 @@ void sid3_reset(SID3* sid3) sid3->chan[i].adsr.d = 0x8; sid3->chan[i].adsr.s = 0x80; sid3->chan[i].adsr.r = 0x07; - sid3->chan[i].adsr.vol = 0x20; + sid3->chan[i].adsr.vol = 0xf0; + sid3->chan[i].adsr.hold_zero = true; //.... } @@ -325,7 +328,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr) int sid3_adsr_output(sid3_channel_adsr* adsr, int input) { - return (int)(input * ((int64_t)adsr->envelope_counter * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL)); + return (int)((int64_t)input * (int64_t)adsr->envelope_counter * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL); } void sid3_write(SID3* sid3, uint8_t address, uint8_t data) @@ -462,6 +465,93 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data) } break; } + case 10: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].frequency &= 0x00ffff; + sid3->chan[channel].frequency |= data << 16; + } + else + { + sid3->wave_chan.frequency &= 0x00ffff; + sid3->wave_chan.frequency |= data << 16; + } + break; + } + case 11: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].frequency &= 0xff00ff; + sid3->chan[channel].frequency |= data << 8; + } + else + { + sid3->wave_chan.frequency &= 0xff00ff; + sid3->wave_chan.frequency |= data << 8; + } + break; + } + case 12: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].frequency &= 0xffff00; + sid3->chan[channel].frequency |= data; + } + else + { + sid3->wave_chan.frequency &= 0xffff00; + sid3->wave_chan.frequency |= data; + } + break; + } + default: break; + } +} + +uint16_t sid3_pulse(uint32_t acc, uint16_t pw) // 0-FFFF pulse width range +{ + return (((acc >> ((SID3_ACC_BITS - 16))) >= ((pw == 0xffff ? pw + 1 : pw)) ? (0xffff) : 0)); +} + +uint16_t sid3_saw(uint32_t acc) +{ + return (acc >> (SID3_ACC_BITS - 16)) & (0xffff); +} + +uint16_t sid3_triangle(uint32_t acc) +{ + return (((acc < (1 << (SID3_ACC_BITS - 1))) ? ~acc : acc) >> (SID3_ACC_BITS - 17)); +} + +uint16_t sid3_get_waveform(sid3_channel* ch) +{ + switch(ch->mix_mode) + { + case SID3_MIX_8580: + { + switch(ch->waveform) + { + case SID3_WAVE_TRIANGLE: + { + return sid3_triangle(ch->accumulator); + break; + } + case SID3_WAVE_SAW: + { + return sid3_saw(ch->accumulator); + break; + } + case SID3_WAVE_PULSE: + { + return sid3_pulse(ch->accumulator, ch->pw); + break; + } + } + break; + } default: break; } } @@ -470,13 +560,37 @@ void sid3_clock(SID3* sid3) { SAFETY_HEADER + sid3->output_l = sid3->output_r = 0; + for(int i = 0; i < SID3_NUM_CHANNELS - 1; i++) { - sid3_adsr_clock(&sid3->chan[i].adsr); - sid3->output_l = sid3_adsr_output(&sid3->chan[i].adsr, 0xff); - sid3->output_r = sid3_adsr_output(&sid3->chan[i].adsr, 0xff); + sid3_channel* ch = &sid3->chan[i]; + + uint32_t prev_acc = ch->accumulator; - sid3->channel_output[i] = sid3_adsr_output(&sid3->chan[i].adsr, 0xff); + ch->accumulator += ch->frequency; + + if(ch->accumulator & (1 << SID3_ACC_BITS)) + { + ch->sync_bit = 1; + } + else + { + ch->sync_bit = 0; + } + + ch->accumulator &= SID3_ACC_MASK; + + //todo: phase mod + + int waveform = sid3_get_waveform(ch); + waveform -= 0x7fff; + + sid3_adsr_clock(&ch->adsr); + sid3->output_l += sid3_adsr_output(&ch->adsr, waveform / 1024); + sid3->output_r += sid3_adsr_output(&ch->adsr, waveform / 1024); + + sid3->channel_output[i] = sid3_adsr_output(&ch->adsr, waveform / 1024); } } diff --git a/src/engine/platform/sound/sid3.h b/src/engine/platform/sound/sid3.h index 78cbd22ea..98fb86611 100644 --- a/src/engine/platform/sound/sid3.h +++ b/src/engine/platform/sound/sid3.h @@ -21,6 +21,9 @@ extern "C" { #define SID3_NUM_SPECIAL_WAVES 28 #define SID3_SPECIAL_WAVE_LENGTH 16384 +#define SID3_ACC_BITS 30 +#define SID3_ACC_MASK ((1UL << SID3_ACC_BITS) - 1) + enum Flags { SID3_CHAN_ENABLE_GATE = 1, @@ -95,6 +98,7 @@ typedef struct typedef struct { uint32_t accumulator; + uint8_t sync_bit; uint32_t frequency; uint32_t noise_accumulator; @@ -125,6 +129,7 @@ typedef struct typedef struct { uint32_t accumulator; + uint8_t sync_bit; uint32_t frequency; uint16_t streamed_sample;