Created
November 28, 2022 12:41
-
-
Save ITotalJustice/2834e3ea28c65bb4cfc4cc5a2e096e22 to your computer and use it in GitHub Desktop.
nes square
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "apu.h" | |
| uint8_t envelope_get_volume(const struct Nes_ApuEnvelope* envelope) | |
| { | |
| return envelope->constant_volume_flag ? envelope->volume : envelope->counter; | |
| } | |
| void envelope_reload(struct Nes_ApuEnvelope* envelope) | |
| { | |
| envelope->start_flag = true; | |
| } | |
| void clock_envelope(struct Nes_ApuEnvelope* envelope) | |
| { | |
| if (envelope->start_flag) | |
| { | |
| envelope->counter = 15; | |
| envelope->divider = envelope->volume; | |
| envelope->start_flag = false; | |
| } | |
| else | |
| { | |
| if (envelope->divider == 0) | |
| { | |
| envelope->divider = envelope->volume; | |
| if (envelope->counter != 0) | |
| { | |
| envelope->counter--; | |
| } | |
| else if (envelope->loop_flag) | |
| { | |
| envelope->counter = 15; | |
| } | |
| } | |
| else | |
| { | |
| envelope->divider--; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "apu.h" | |
| static const uint8_t LENGTH_COUNTER_TABLE[0x20] = | |
| { | |
| 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06, | |
| 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E, | |
| 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16, | |
| 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E, | |
| }; | |
| void length_reload(struct Nes_ApuLength* length, uint8_t index) | |
| { | |
| length->counter = LENGTH_COUNTER_TABLE[index]; | |
| } | |
| void clock_length(struct Nes_ApuLength* length) | |
| { | |
| if (length->halt) | |
| { | |
| return; | |
| } | |
| if (length->counter > 0) | |
| { | |
| length->counter--; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "../nes.h" | |
| #include "../internal.h" | |
| #include "apu.h" | |
| static const bool SQUARE_DUTY[4][8] = | |
| { | |
| [0] = { 0, 1, 0, 0, 0, 0, 0, 0 }, // (12.5%) | |
| [1] = { 0, 1, 1, 0, 0, 0, 0, 0 }, // (25%) | |
| [2] = { 0, 1, 1, 1, 1, 0, 0, 0 }, // (50%) | |
| [3] = { 1, 0, 0, 1, 1, 1, 1, 1 }, // (25% negated) | |
| }; | |
| bool is_square1_enabled(const struct NES_Core* nes) | |
| { | |
| return STATUS.square1_enable; | |
| } | |
| bool is_square2_enabled(const struct NES_Core* nes) | |
| { | |
| return STATUS.square1_enable; | |
| } | |
| static uint16_t get_square_freq(const struct NES_Square* square) | |
| { | |
| return square->timer_reload; | |
| } | |
| void clock_square_length(struct NES_Square* square) | |
| { | |
| clock_length(&square->length); | |
| } | |
| void clock_square_envelope(struct NES_Square* square) | |
| { | |
| clock_envelope(&square->envelope); | |
| } | |
| void clock_square_sweep(struct NES_Square* square, bool is_square2) | |
| { | |
| clock_sweep(&square->sweep, &square->timer_reload, is_square2); | |
| } | |
| static void clock_square_duty(struct NES_Square* square) | |
| { | |
| ++square->duty_index; | |
| square->duty_index &= 0x7; | |
| } | |
| uint8_t sample_square(const struct NES_Square* square) | |
| { | |
| if (square->length.counter == 0) | |
| { | |
| return 0; | |
| } | |
| if (square->sweep.muted) | |
| { | |
| return 0; | |
| } | |
| if (!SQUARE_DUTY[square->duty][square->duty_index]) | |
| { | |
| return 0; | |
| } | |
| return envelope_get_volume(&square->envelope); | |
| } | |
| void tick_square_channel(struct NES_Square* square, const uint16_t cycles_elapsed) | |
| { | |
| if (square->timer > 0 || get_square_freq(square)) | |
| { | |
| square->timer -= cycles_elapsed; | |
| if (square->timer <= 0) | |
| { | |
| square->timer += get_square_freq(square) * 2 + 1; | |
| clock_square_duty(square); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "apu.h" | |
| void sweep_update_target_period(struct NES_ApuSweep* sweep, uint16_t timer, bool is_square2) | |
| { | |
| const uint16_t current_period = timer; | |
| const uint16_t sum = current_period >> sweep->shift_count; | |
| if (sweep->negate_flag) | |
| { | |
| sweep->target_period = current_period - sum; | |
| if (!is_square2) | |
| { | |
| sweep->target_period--; | |
| } | |
| } | |
| else | |
| { | |
| sweep->target_period = current_period + sum; | |
| } | |
| if (current_period < 8 || sweep->target_period > 0x7FF) | |
| { | |
| sweep->muted = true; | |
| } | |
| else | |
| { | |
| sweep->muted = false; | |
| } | |
| } | |
| void clock_sweep(struct NES_ApuSweep* sweep, uint16_t* timer, bool is_square2) | |
| { | |
| if (sweep->divider == 0 && sweep->enabled_flag && !sweep->muted && sweep->shift_count) | |
| { | |
| *timer = sweep->target_period; | |
| sweep_update_target_period(sweep, *timer, is_square2); | |
| } | |
| if (sweep->divider == 0 || sweep->reload_flag) | |
| { | |
| sweep->divider = sweep->period; | |
| sweep->reload_flag = false; | |
| } | |
| else | |
| { | |
| sweep->divider--; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment