diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 08d3ffe..b20916c 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -113,12 +113,13 @@ void _play_note(int ch, const xm_pattern_format_t * pf) wait(); aica_sound.channel[ch].PLFOS(0); } - wait(); aica_sound.channel[ch].KYONB(1); + state.channel[ch].keyon = 1; + wait(); aica_sound.channel[ch].KYONB(0); } void play_note_effect(int ch, const xm_pattern_format_t * pf) { - int effect_tick = (state.tick / 2) % state.ticks_per_line; + int effect_tick = state.tick % state.ticks_per_line; switch (pf->effect_type) { case 0x04: // 4 vibrato @@ -207,51 +208,75 @@ void execute_line(int line_index) void interrupt() { - bool keyoff_tick = (state.tick + 1) % (state.ticks_per_line * 2) == 0; - bool note_tick = state.tick % (state.ticks_per_line * 2) == 0; - bool effect_tick = (state.tick & 1) == 0; - bool pattern_break_tick = (state.tick % (state.ticks_per_line * 2)) == (state.ticks_per_line * 2 - 1); + state.interrupt_clock += 1; + // execute keyons + for (int ch = 0; ch < 64; ch++) { + /* + if (state.channel[ch].keyon == 2) { + int sgc = aica_sound.common.SGC(); + if (sgc == 3) { + wait(); aica_sound.channel[ch].KYONB(1); + state.channel[ch].keyon = 0; + } + break; + } else if (state.channel[ch].keyon == 1) { + wait(); aica_sound.common.afsel_mslc_mobuf + = aica::afsel_mslc_mobuf::AFSEL(0) + | aica::afsel_mslc_mobuf::MSLC(ch); + state.channel[ch].keyon = 2; + break; + } + */ + if (state.channel[ch].keyon != 0) { + wait(); aica_sound.channel[ch].KYONB(1); + state.channel[ch].keyon = 0; + } + } + wait(); aica_sound.channel[0].KYONEX(1); - if (keyoff_tick) { - // execute keyoffs - execute_line(state.next_line_index); - } - - if (state.pattern_break >= 0 && pattern_break_tick) { - printf("pattern_break\n"); - next_pattern(); + if ((state.interrupt_clock % state.tick_rate) != 0) { + return; } + int tick = state.tick % state.ticks_per_line; + bool note_tick = tick == 0; if (note_tick) { // execute notes state.line_index = state.next_line_index; state.next_line_index += 1; execute_line(state.line_index); - } else if (effect_tick) { + } else { // execute effects execute_line(state.line_index); } wait(); aica_sound.channel[0].KYONEX(1); - int note_index = state.next_line_index * state.xm.number_of_channels; - bool end_of_pattern = note_index >= state.xm.pattern_note_count[state.pattern_index]; - if (end_of_pattern && pattern_break_tick) { - printf("end_of_pattern\n"); - next_pattern(); + bool pattern_break_tick = tick == (state.ticks_per_line - 1); + if (pattern_break_tick) { + if (state.pattern_break >= 0) { + printf("pattern_break\n"); + next_pattern(); + } + int note_index = state.next_line_index * state.xm.number_of_channels; + bool end_of_pattern = note_index >= state.xm.pattern_note_count[state.pattern_index]; + if (end_of_pattern) { + printf("end_of_pattern\n"); + next_pattern(); + } } state.tick += 1; } -void init() +void init(float clock_multiplier) { // 195 = 1ms // 2500 / bpm milliseconds int default_bpm = s16(&state.xm.header->default_bpm); int default_tempo = s16(&state.xm.header->default_tempo); - int tick_rate = 195.32 * 2500 / default_bpm; + int tick_rate = clock_multiplier * 2500 / default_bpm; printf("default_bpm %d\n", default_bpm); printf("default_tempo %d\n", default_tempo); diff --git a/src/interpreter.hpp b/src/interpreter.hpp index 61efb82..d716c0d 100644 --- a/src/interpreter.hpp +++ b/src/interpreter.hpp @@ -7,10 +7,12 @@ namespace interpreter { constexpr int max_channels = 64; struct channel_state { - int instrument; + uint8_t instrument; + uint8_t keyon; }; struct interpreter_state { + int interrupt_clock; int tick_rate; int ticks_per_line; int tick; @@ -27,6 +29,6 @@ struct interpreter_state { extern struct interpreter_state state; void interrupt(); -void init(); +void init(float clock_multiplier); } diff --git a/src/main.cpp b/src/main.cpp index f526577..f640aa7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,8 @@ #include "maple/maple_bus_commands.hpp" #include "maple/maple_bus_ft0.hpp" +#include "aica/aica.hpp" + #include "interrupt.hpp" #include "graphics.hpp" #include "interpreter.hpp" @@ -43,6 +45,13 @@ void vbr600() } graphics_interrupt(istnrm); + } else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x360) { // AICA + wait(); aica_sound.common.mcire = (1 << 6); // interrupt timer A + wait(); aica_sound.common.tactl_tima = + aica::tactl_tima::TACTL(0) // increment once every sample + | aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts + ; + interpreter::interrupt(); } else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x400) { // TMU0 sh7091.TMU.TCR0 = tmu::tcr0::UNIE @@ -174,7 +183,7 @@ void input_update() last_b = b; } -void load_xm() +void load_xm(float clock_multiplier) { using namespace interpreter; @@ -187,8 +196,9 @@ void load_xm() buf, sample_data, sample_data_length); - interpreter::init(); + interpreter::init(clock_multiplier); sound_init(sample_data, sample_data_ix, state.tick_rate); + printf("tick_rate %d\n", state.tick_rate); } #include "memorymap.hpp" @@ -225,7 +235,9 @@ void main() { serial::init(0); - load_xm(); + //const float tmu_clock_multiplier = 195.32; + const float aica_clock_multiplier = 44.1; + load_xm(aica_clock_multiplier); graphics_init(); test_pattern(); @@ -237,6 +249,8 @@ void main() | istnrm::v_blank_in | istnrm::end_of_transferring_opaque_list; + system.IML4EXT = istext::aica; + static uint8_t __attribute__((aligned(32))) ta_parameter_buf[1024 * 1024 * 1]; ta_parameter_writer writer = ta_parameter_writer(ta_parameter_buf, (sizeof (ta_parameter_buf))); diff --git a/src/sound.cpp b/src/sound.cpp index 71ea7ee..45dc7f4 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -17,8 +17,6 @@ #include "assert.h" -#include "interpreter.hpp" - void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length) { using namespace dmac; @@ -151,6 +149,7 @@ void sound_init(uint8_t * sample_data, int sample_data_ix, int tick_rate) | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume ; + /* sh7091.TMU.TSTR = 0; // stop all timers sh7091.TMU.TCOR0 = tick_rate / 2; sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture; @@ -161,4 +160,13 @@ void sound_init(uint8_t * sample_data, int sample_data_ix, int tick_rate) sh7091.TMU.TSTR = tmu::tstr::str0::counter_start; sh7091.INTC.IPRA = intc::ipra::TMU0(1); + */ + + wait(); aica_sound.common.tactl_tima = + aica::tactl_tima::TACTL(0) // increment once every sample + | aica::tactl_tima::TIMA(0xffff) // interrupt after 1 counts + ; + + wait(); aica_sound.common.mcieb = (1 << 6); // interrupt timer A + wait(); aica_sound.common.mcire = (1 << 6); // interrupt timer A }