switch to AICA timing
This commit is contained in:
parent
01eaa32e37
commit
2066923f10
@ -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].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)
|
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) {
|
switch (pf->effect_type) {
|
||||||
case 0x04: // 4 vibrato
|
case 0x04: // 4 vibrato
|
||||||
@ -207,51 +208,75 @@ void execute_line(int line_index)
|
|||||||
|
|
||||||
void interrupt()
|
void interrupt()
|
||||||
{
|
{
|
||||||
bool keyoff_tick = (state.tick + 1) % (state.ticks_per_line * 2) == 0;
|
state.interrupt_clock += 1;
|
||||||
bool note_tick = state.tick % (state.ticks_per_line * 2) == 0;
|
// execute keyons
|
||||||
bool effect_tick = (state.tick & 1) == 0;
|
for (int ch = 0; ch < 64; ch++) {
|
||||||
bool pattern_break_tick = (state.tick % (state.ticks_per_line * 2)) == (state.ticks_per_line * 2 - 1);
|
/*
|
||||||
|
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) {
|
if ((state.interrupt_clock % state.tick_rate) != 0) {
|
||||||
// execute keyoffs
|
return;
|
||||||
execute_line<rekey_note>(state.next_line_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.pattern_break >= 0 && pattern_break_tick) {
|
|
||||||
printf("pattern_break\n");
|
|
||||||
next_pattern();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tick = state.tick % state.ticks_per_line;
|
||||||
|
bool note_tick = tick == 0;
|
||||||
if (note_tick) {
|
if (note_tick) {
|
||||||
// execute notes
|
// execute notes
|
||||||
state.line_index = state.next_line_index;
|
state.line_index = state.next_line_index;
|
||||||
state.next_line_index += 1;
|
state.next_line_index += 1;
|
||||||
|
|
||||||
execute_line<play_note>(state.line_index);
|
execute_line<play_note>(state.line_index);
|
||||||
} else if (effect_tick) {
|
} else {
|
||||||
// execute effects
|
// execute effects
|
||||||
execute_line<play_note_effect>(state.line_index);
|
execute_line<play_note_effect>(state.line_index);
|
||||||
}
|
}
|
||||||
wait(); aica_sound.channel[0].KYONEX(1);
|
wait(); aica_sound.channel[0].KYONEX(1);
|
||||||
|
|
||||||
|
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;
|
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];
|
bool end_of_pattern = note_index >= state.xm.pattern_note_count[state.pattern_index];
|
||||||
if (end_of_pattern && pattern_break_tick) {
|
if (end_of_pattern) {
|
||||||
printf("end_of_pattern\n");
|
printf("end_of_pattern\n");
|
||||||
next_pattern();
|
next_pattern();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state.tick += 1;
|
state.tick += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
void init(float clock_multiplier)
|
||||||
{
|
{
|
||||||
// 195 = 1ms
|
// 195 = 1ms
|
||||||
// 2500 / bpm milliseconds
|
// 2500 / bpm milliseconds
|
||||||
|
|
||||||
int default_bpm = s16(&state.xm.header->default_bpm);
|
int default_bpm = s16(&state.xm.header->default_bpm);
|
||||||
int default_tempo = s16(&state.xm.header->default_tempo);
|
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_bpm %d\n", default_bpm);
|
||||||
printf("default_tempo %d\n", default_tempo);
|
printf("default_tempo %d\n", default_tempo);
|
||||||
|
@ -7,10 +7,12 @@ namespace interpreter {
|
|||||||
constexpr int max_channels = 64;
|
constexpr int max_channels = 64;
|
||||||
|
|
||||||
struct channel_state {
|
struct channel_state {
|
||||||
int instrument;
|
uint8_t instrument;
|
||||||
|
uint8_t keyon;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct interpreter_state {
|
struct interpreter_state {
|
||||||
|
int interrupt_clock;
|
||||||
int tick_rate;
|
int tick_rate;
|
||||||
int ticks_per_line;
|
int ticks_per_line;
|
||||||
int tick;
|
int tick;
|
||||||
@ -27,6 +29,6 @@ struct interpreter_state {
|
|||||||
|
|
||||||
extern struct interpreter_state state;
|
extern struct interpreter_state state;
|
||||||
void interrupt();
|
void interrupt();
|
||||||
void init();
|
void init(float clock_multiplier);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
20
src/main.cpp
20
src/main.cpp
@ -6,6 +6,8 @@
|
|||||||
#include "maple/maple_bus_commands.hpp"
|
#include "maple/maple_bus_commands.hpp"
|
||||||
#include "maple/maple_bus_ft0.hpp"
|
#include "maple/maple_bus_ft0.hpp"
|
||||||
|
|
||||||
|
#include "aica/aica.hpp"
|
||||||
|
|
||||||
#include "interrupt.hpp"
|
#include "interrupt.hpp"
|
||||||
#include "graphics.hpp"
|
#include "graphics.hpp"
|
||||||
#include "interpreter.hpp"
|
#include "interpreter.hpp"
|
||||||
@ -43,6 +45,13 @@ void vbr600()
|
|||||||
}
|
}
|
||||||
|
|
||||||
graphics_interrupt(istnrm);
|
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
|
} else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x400) { // TMU0
|
||||||
sh7091.TMU.TCR0
|
sh7091.TMU.TCR0
|
||||||
= tmu::tcr0::UNIE
|
= tmu::tcr0::UNIE
|
||||||
@ -174,7 +183,7 @@ void input_update()
|
|||||||
last_b = b;
|
last_b = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_xm()
|
void load_xm(float clock_multiplier)
|
||||||
{
|
{
|
||||||
using namespace interpreter;
|
using namespace interpreter;
|
||||||
|
|
||||||
@ -187,8 +196,9 @@ void load_xm()
|
|||||||
buf,
|
buf,
|
||||||
sample_data,
|
sample_data,
|
||||||
sample_data_length);
|
sample_data_length);
|
||||||
interpreter::init();
|
interpreter::init(clock_multiplier);
|
||||||
sound_init(sample_data, sample_data_ix, state.tick_rate);
|
sound_init(sample_data, sample_data_ix, state.tick_rate);
|
||||||
|
printf("tick_rate %d\n", state.tick_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "memorymap.hpp"
|
#include "memorymap.hpp"
|
||||||
@ -225,7 +235,9 @@ void main()
|
|||||||
{
|
{
|
||||||
serial::init(0);
|
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();
|
graphics_init();
|
||||||
|
|
||||||
test_pattern();
|
test_pattern();
|
||||||
@ -237,6 +249,8 @@ void main()
|
|||||||
| istnrm::v_blank_in
|
| istnrm::v_blank_in
|
||||||
| istnrm::end_of_transferring_opaque_list;
|
| istnrm::end_of_transferring_opaque_list;
|
||||||
|
|
||||||
|
system.IML4EXT = istext::aica;
|
||||||
|
|
||||||
static uint8_t __attribute__((aligned(32))) ta_parameter_buf[1024 * 1024 * 1];
|
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)));
|
ta_parameter_writer writer = ta_parameter_writer(ta_parameter_buf, (sizeof (ta_parameter_buf)));
|
||||||
|
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
#include "interpreter.hpp"
|
|
||||||
|
|
||||||
void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length)
|
void g2_aica_dma(uint32_t g2_address, uint32_t system_address, int length)
|
||||||
{
|
{
|
||||||
using namespace dmac;
|
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
|
| aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
sh7091.TMU.TSTR = 0; // stop all timers
|
sh7091.TMU.TSTR = 0; // stop all timers
|
||||||
sh7091.TMU.TCOR0 = tick_rate / 2;
|
sh7091.TMU.TCOR0 = tick_rate / 2;
|
||||||
sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture;
|
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.TMU.TSTR = tmu::tstr::str0::counter_start;
|
||||||
|
|
||||||
sh7091.INTC.IPRA = intc::ipra::TMU0(1);
|
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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user