diff --git a/ay-3-8912.cpp b/ay-3-8912.cpp index 3eaaf57..d3c57e5 100644 --- a/ay-3-8912.cpp +++ b/ay-3-8912.cpp @@ -1,6 +1,7 @@ #include "ay-3-8912.h" #include "z80.h" #include +#include "zx_ula.h" #define MIXER_REG_A_TONE 0x01 #define MIXER_REG_B_TONE 0x02 @@ -70,33 +71,34 @@ namespace audio case 0: case 1: { uint16_t freq = registers[0] | ((registers[1] & 0xf) << 8); - channel_a_tone_freq = clock / freq; + channel_a_tone_freq = clock / freq==0?1:freq; channel_a_tone_freq_counter = 0; break; } case 2: case 3: { uint16_t freq = registers[2] | ((registers[3] & 0xf) << 8); - channel_b_tone_freq = clock / freq; + channel_b_tone_freq = clock / freq==0?1:freq; channel_b_tone_freq_counter = 0; break; } case 4: case 5: { uint16_t freq = registers[4] | ((registers[5] & 0xf) << 8); - channel_c_tone_freq = clock / freq; + channel_c_tone_freq = clock / freq==0?1:freq; channel_c_tone_freq_counter = 0; break; } case 6: { - noise_freq = clock / (registers[6] & 0x1f); + uint8_t freq = (registers[6] & 0x1f); + noise_freq = clock / freq==0?1:freq; noise_freq_counter = 0; break; } case 11: case 12: { uint16_t freq = registers[11] | (registers[12] << 8); - envelope_freq = clock / freq; + envelope_freq = clock / freq==0?1:freq; break; } case 13: @@ -112,13 +114,9 @@ namespace audio void init() { - SDL_AudioSpec audioSpec{SAMPLING_FREQ, AUDIO_U8, 1, 0, AUDIO_BUFFER_SIZE, 0, 0, NULL, NULL}; - sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); - cycles_per_sample = z80::getClock() / SAMPLING_FREQ; reset(); z80::connect_port(0xfffd, 0xffff, audio::read_register, audio::select_register); z80::connect_port(0xbffd, 0xffff, nullptr, audio::write_register); - resume(); } void reset() @@ -127,97 +125,96 @@ namespace audio for (int i=0; i<16;++i) registers[i]=0; } - void silence() - { - SDL_PauseAudioDevice(sdlAudioDevice, 1); - } - - void resume() - { - SDL_PauseAudioDevice(sdlAudioDevice, 0); - } - void update(uint32_t dt) { - for (int i=0;i> 1; - // Oscillate (0-1) channel B tone level given its frequency - channel_b_tone_freq_counter++; - if (channel_b_tone_freq_counter == channel_b_tone_freq) { - channel_b_tone_freq_counter = 0; - channel_b_tone_level = channel_b_tone_level ^ 1; - } + // Oscillate (0-1) channel A tone level given its frequency + channel_a_tone_freq_counter+=dt; + if (channel_a_tone_freq_counter >= channel_a_tone_freq) { + channel_a_tone_freq_counter -= channel_a_tone_freq; + channel_a_tone_level = channel_a_tone_level ^ 1; + } - // Oscillate (0-1) channel C tone level given its frequency - channel_c_tone_freq_counter++; - if (channel_c_tone_freq_counter == channel_c_tone_freq) { - channel_c_tone_freq_counter = 0; - channel_c_tone_level = channel_c_tone_level ^ 1; - } + // Oscillate (0-1) channel B tone level given its frequency + channel_b_tone_freq_counter+=dt; + if (channel_b_tone_freq_counter >= channel_b_tone_freq) { + channel_b_tone_freq_counter -= channel_b_tone_freq; + channel_b_tone_level = channel_b_tone_level ^ 1; + } - // Oscillate (0-1) noise level given its frequency and shift register - noise_freq_counter++; - if (noise_freq_counter == noise_freq) { - noise_freq_counter = 0; - noise_level = noise_level ^ shiftreg; - uint32_t newbit = shiftreg ^ (shiftreg >> 3); - shiftreg = ((shiftreg >> 1) & 0xff) | ((newbit << 16) & 0x100); - } + // Oscillate (0-1) channel C tone level given its frequency + channel_c_tone_freq_counter+=dt; + if (channel_c_tone_freq_counter >= channel_c_tone_freq) { + channel_c_tone_freq_counter -= channel_c_tone_freq; + channel_c_tone_level = channel_c_tone_level ^ 1; + } - // Mix tone and noise on channel A given register 7 values - channel_a_level = 1; - if (registers[7] & MIXER_REG_A_TONE) channel_a_level &= channel_a_tone_level; - if (registers[7] & MIXER_REG_A_NOISE) channel_a_level &= noise_level; - - // Mix tone and noise on channel B given register 7 values - channel_b_level = 1; - if (registers[7] & MIXER_REG_B_TONE) channel_b_level &= channel_b_tone_level; - if (registers[7] & MIXER_REG_B_NOISE) channel_b_level &= noise_level; - - // Mix tone and noise on channel C given register 7 values - channel_c_level = 1; - if (registers[7] & MIXER_REG_C_TONE) channel_c_level &= channel_c_tone_level; - if (registers[7] & MIXER_REG_C_NOISE) channel_c_level &= noise_level; + // Oscillate (0-1) noise level given its frequency and shift register + noise_freq_counter+=dt; + if (noise_freq_counter >= noise_freq) { + noise_freq_counter -= noise_freq; + noise_level = noise_level ^ shiftreg; + uint32_t newbit = shiftreg ^ (shiftreg >> 3); + shiftreg = ((shiftreg >> 1) & 0xff) | ((newbit << 16) & 0x100); + } + // Develop (0-15) envelope volume given its frequency and shape + envelope_freq_counter+=dt; + if (envelope_freq_counter >= envelope_freq) { + envelope_freq_counter -= envelope_freq; - // Develop (0-15) envelope volume given its frequency and shape - envelope_freq_counter++; - if (envelope_freq_counter == envelope_freq) { - envelope_freq_counter = 0; - - envelope_volume += envelope_direction; - if ( (envelope_volume > 15) || (envelope_volume < 0) ) { - switch(registers[13]&0xf) { - case 8: - case 12: - envelope_volume &= 0x0f; - break; - case 10: - case 14: - envelope_direction = -envelope_direction; - envelope_volume += envelope_direction; - case 11: - case 13: - envelope_direction = 0; - envelope_volume = 15; - default: - envelope_direction = 0; - envelope_volume = 0; - } + envelope_volume += envelope_direction; + if ( (envelope_volume > 15) || (envelope_volume < 0) ) { + switch(registers[13]&0xf) { + case 8: + case 12: + envelope_volume &= 0x0f; + break; + case 10: + case 14: + envelope_direction = -envelope_direction; + envelope_volume += envelope_direction; + case 11: + case 13: + envelope_direction = 0; + envelope_volume = 15; + default: + envelope_direction = 0; + envelope_volume = 0; } } - - uint8_t channel_a_volume = (registers[8]&0x10) ? envelope_volume : registers[8]&0xf; - uint8_t channel_b_volume = (registers[9]&0x10) ? envelope_volume : registers[9]&0xf; - uint8_t channel_c_volume = (registers[10]&0x10) ? envelope_volume : registers[10]&0xf; } } + uint8_t get_sample() + { + // Mix tone and noise on channel A given register 7 values + channel_a_level = 1; + if (registers[7] & MIXER_REG_A_TONE) channel_a_level &= channel_a_tone_level; + if (registers[7] & MIXER_REG_A_NOISE) channel_a_level &= noise_level; + + // Mix tone and noise on channel B given register 7 values + channel_b_level = 1; + if (registers[7] & MIXER_REG_B_TONE) channel_b_level &= channel_b_tone_level; + if (registers[7] & MIXER_REG_B_NOISE) channel_b_level &= noise_level; + + // Mix tone and noise on channel C given register 7 values + channel_c_level = 1; + if (registers[7] & MIXER_REG_C_TONE) channel_c_level &= channel_c_tone_level; + if (registers[7] & MIXER_REG_C_NOISE) channel_c_level &= noise_level; + + const uint8_t channel_a_volume = (registers[8]&0x10) ? envelope_volume : registers[8]&0xf; + const uint8_t channel_b_volume = (registers[9]&0x10) ? envelope_volume : registers[9]&0xf; + const uint8_t channel_c_volume = (registers[10]&0x10) ? envelope_volume : registers[10]&0xf; + + const uint8_t channel_a_sample = volume_table[(channel_a_level&1) * channel_a_volume] >> 1; + const uint8_t channel_b_sample = volume_table[(channel_b_level&1) * channel_b_volume] >> 1; + const uint8_t channel_c_sample = volume_table[(channel_c_level&1) * channel_c_volume] >> 1; + + uint8_t sample = (channel_a_sample+channel_b_sample+channel_c_sample)&0xff; + zx_ula::set_border_color(sample&0xf); + return sample; + } + } diff --git a/ay-3-8912.h b/ay-3-8912.h index 61fe593..4a4e3da 100644 --- a/ay-3-8912.h +++ b/ay-3-8912.h @@ -10,7 +10,7 @@ namespace audio void init(); void reset(); - void silence(); - void resume(); void update(uint32_t dt); + + uint8_t get_sample(); } diff --git a/main.cpp b/main.cpp index 8a79da4..1c2b755 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,7 @@ #include "z80viewer.h" //#include "zx_128bankviewer.h" //#include "zx_128pageviewer.h" +#include "ay-3-8912.h" //uint8_t memory[65536]; uint32_t time = 0; @@ -78,23 +79,24 @@ namespace actions int main(int argc, char *argv[]) { - const uint32_t clock = 3500000; - //const uint32_t clock = 3546900; + //const uint32_t clock = 3500000; + const uint32_t clock = 3546900; const uint32_t update_freq = clock / 10; //new zx_48mem(); //new zx_128mem(); - mem::init(ZX_48K); + mem::init(ZX_128K); z80dis::loadSymbols(); z80::setClock(clock); z80::reset(); z80::connect_port(0xfe, 0x0001, zx_ula::port_in, zx_ula::port_out); + audio::init(); SDL_Init(SDL_INIT_EVERYTHING); z80debug::init(); - zxscreen::init(SCREEN_MODE_48K); - //zxscreen::init(SCREEN_MODE_128K); + //zxscreen::init(SCREEN_MODE_48K); + zxscreen::init(SCREEN_MODE_128K); //z80viewer *v = new zx_128bankviewer(); //v->show(); @@ -131,6 +133,7 @@ int main(int argc, char *argv[]) speaker::init(); speaker::register_source(zx_ula::get_sample); + speaker::register_source(audio::get_sample); zx_tape::load("ROBOCOP1.TAP"); @@ -244,7 +247,7 @@ int main(int argc, char *argv[]) uint8_t dt = z80::step(); t_states += dt; zx_tape::update(dt); - + audio::update(dt); speaker::update(dt); zxscreen::refresh(dt); if (z80debug::debugging()) break; diff --git a/z80debug.cpp b/z80debug.cpp index c2652f2..1ff1f89 100644 --- a/z80debug.cpp +++ b/z80debug.cpp @@ -10,6 +10,7 @@ #include "ui.h" #include "ui_window.h" #include "zx_screen.h" +#include "ay-3-8912.h" #define RESIZING_NONE 0 #define RESIZING_MEMORY 1 @@ -792,6 +793,7 @@ namespace z80debug if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0) { uint8_t dt = z80::step(); zx_tape::update(dt); + audio::update(dt); speaker::update(dt); zxscreen::fullrefresh(); z80analyze::refresh(); diff --git a/zx_ula.cpp b/zx_ula.cpp index 4f6ef17..a839338 100644 --- a/zx_ula.cpp +++ b/zx_ula.cpp @@ -223,6 +223,7 @@ namespace zx_ula } uint8_t get_border_color() { return border_color; } + void set_border_color(uint8_t col) { border_color = col; } uint8_t get_ear() { return ear; } void set_ear(const uint8_t val) { ear = val; } diff --git a/zx_ula.h b/zx_ula.h index bc39f4c..0b3bf18 100644 --- a/zx_ula.h +++ b/zx_ula.h @@ -8,6 +8,7 @@ namespace zx_ula void port_out(int port, int val); uint8_t get_border_color(); + void set_border_color(uint8_t col); uint8_t get_ear(); void set_ear(const uint8_t val);