Path: blob/master/libsnes/bsnes/gameboy/apu/square1/square1.cpp
2 views
#ifdef APU_CPP12bool APU::Square1::dac_enable() {3return (envelope_volume || envelope_direction);4}56void APU::Square1::run() {7if(period && --period == 0) {8period = 4 * (2048 - frequency);9phase++;10switch(duty) {11case 0: duty_output = (phase == 6); break; //______-_12case 1: duty_output = (phase >= 6); break; //______--13case 2: duty_output = (phase >= 4); break; //____----14case 3: duty_output = (phase <= 5); break; //------__15}16}1718uint4 sample = (duty_output ? volume : (uint4)0);19if(enable == false) sample = 0;2021output = sample;22}2324void APU::Square1::sweep(bool update) {25if(sweep_enable == false) return;2627sweep_negate = sweep_direction;28unsigned delta = frequency_shadow >> sweep_shift;29signed freq = frequency_shadow + (sweep_negate ? -delta : delta);3031if(freq > 2047) {32enable = false;33} else if(sweep_shift && update) {34frequency_shadow = freq;35frequency = freq & 2047;36period = 4 * (2048 - frequency);37}38}3940void APU::Square1::clock_length() {41if(counter && length) {42if(--length == 0) enable = false;43}44}4546void APU::Square1::clock_sweep() {47if(enable && sweep_frequency && --sweep_period == 0) {48sweep_period = sweep_frequency;49sweep(1);50sweep(0);51}52}5354void APU::Square1::clock_envelope() {55if(enable && envelope_frequency && --envelope_period == 0) {56envelope_period = envelope_frequency;57if(envelope_direction == 0 && volume > 0) volume--;58if(envelope_direction == 1 && volume < 15) volume++;59}60}6162void APU::Square1::write(unsigned r, uint8 data) {63if(r == 0) { //$ff10 NR1064if(sweep_negate && sweep_direction && !(data & 0x08)) enable = false;65sweep_frequency = (data >> 4) & 7;66sweep_direction = data & 0x08;67sweep_shift = data & 0x07;68}6970if(r == 1) { //$ff11 NR1171duty = data >> 6;72length = 64 - (data & 0x3f);73}7475if(r == 2) { //$ff12 NR1276envelope_volume = data >> 4;77envelope_direction = data & 0x08;78envelope_frequency = data & 0x07;79if(dac_enable() == false) enable = false;80}8182if(r == 3) { //$ff13 NR1383frequency = (frequency & 0x0700) | data;84}8586if(r == 4) { //$ff14 NR1487bool initialize = data & 0x80;88counter = data & 0x40;89frequency = ((data & 7) << 8) | (frequency & 0x00ff);9091if(initialize) {92enable = dac_enable();93envelope_period = envelope_frequency;94volume = envelope_volume;95frequency_shadow = frequency;96sweep_period = sweep_frequency;97sweep_enable = sweep_period || sweep_shift;98sweep_negate = false;99if(sweep_shift) sweep(0);100if(length == 0) length = 64;101}102}103104period = 4 * (2048 - frequency);105}106107void APU::Square1::power() {108enable = 0;109110sweep_frequency = 0;111sweep_direction = 0;112sweep_shift = 0;113sweep_negate = 0;114duty = 0;115length = 0;116envelope_volume = 0;117envelope_direction = 0;118envelope_frequency = 0;119frequency = 0;120counter = 0;121122output = 0;123duty_output = 0;124phase = 0;125period = 0;126envelope_period = 0;127sweep_period = 0;128frequency_shadow = 0;129sweep_enable = 0;130volume = 0;131}132133void APU::Square1::serialize(serializer &s) {134s.integer(enable);135136s.integer(sweep_frequency);137s.integer(sweep_direction);138s.integer(sweep_shift);139s.integer(sweep_negate);140s.integer(duty);141s.integer(length);142s.integer(envelope_volume);143s.integer(envelope_direction);144s.integer(envelope_frequency);145s.integer(frequency);146s.integer(counter);147148s.integer(output);149s.integer(duty_output);150s.integer(phase);151s.integer(period);152s.integer(envelope_period);153s.integer(sweep_period);154s.integer(frequency_shadow);155s.integer(sweep_enable);156s.integer(volume);157}158159#endif160161162