diff --git a/example/aica/aica.mk b/example/aica/aica.mk index b5bba4c..bcb103a 100644 --- a/example/aica/aica.mk +++ b/example/aica/aica.mk @@ -15,7 +15,13 @@ AICA_XM_OBJ = \ printf/parse.o \ xm/milkypack01.xm.o \ xm/test.xm.o \ + xm/xmtest.xm.o \ + xm/catch_this_rebel.xm.o \ xm/middle_c.xm.o \ + holly/core.o \ + holly/region_array.o \ + holly/background.o \ + holly/ta_fifo_polygon_converter.o \ $(LIBGCC) example/aica/aica_xm.elf: LDSCRIPT = $(LIB)/main.lds diff --git a/example/aica/aica_xm.cpp b/example/aica/aica_xm.cpp index 08ddceb..89b358c 100644 --- a/example/aica/aica_xm.cpp +++ b/example/aica/aica_xm.cpp @@ -1,3 +1,17 @@ +#include "holly/background.hpp" +#include "holly/core.hpp" +#include "holly/core_bits.hpp" +#include "holly/holly.hpp" +#include "holly/isp_tsp.hpp" +#include "holly/region_array.hpp" +#include "holly/ta_bits.hpp" +#include "holly/ta_fifo_polygon_converter.hpp" +#include "holly/ta_global_parameter.hpp" +#include "holly/ta_parameter.hpp" +#include "holly/ta_vertex_parameter.hpp" +#include "holly/texture_memory_alloc5.hpp" +#include "holly/video_output.hpp" + #include "memorymap.hpp" #include "systembus.hpp" #include "systembus_bits.hpp" @@ -8,6 +22,8 @@ #include "sh7091/serial.hpp" #include "printf/printf.h" +#include "math/float_types.hpp" + #include "assert.h" //#include "example/arm/xm.bin.h" @@ -15,6 +31,10 @@ #include "xm/milkypack01.xm.h" #include "xm/middle_c.xm.h" #include "xm/test.xm.h" +#include "xm/xmtest.xm.h" +#include "xm/catch_this_rebel.xm.h" + +#include "interrupt.hpp" constexpr int max_patterns = 64; constexpr int max_instruments = 128; @@ -32,13 +52,18 @@ struct interpreter_state { int tick_rate; int ticks_per_line; int tick; + int pattern_order_table_index; int pattern_break; int pattern_index; int line_index; // within the current pattern (for debugging) int note_offset; // within the current pattern int next_note_offset; + int number_of_channels; + int song_length; }; +struct interpreter_state state; + void print_u8(int8_t * chars, int length, const char * end) { for (int i = 0; i < length; i++) { @@ -78,6 +103,8 @@ int unpack_sample(int buf, int offset, xm_sample_header_t * sample_header) int loop_start = s32(&sample_header->sample_loop_start); int loop_length = s32(&sample_header->sample_loop_length); + printf("unpack %d %d\n", offset, size); + int loop_type = sample_header->type & 0b11; if (sample_header->type & (1 << 4)) { // 16-bit samples @@ -196,6 +223,18 @@ void xm_init(int buf) offset = xm_samples_init(buf, offset, i, number_of_samples); } printf("end_of_instruments: %d\n", offset); + + int number_of_channels = s16(&xm.header->number_of_channels); + state.number_of_channels = number_of_channels; + printf("number_of_channels: %d\n", number_of_channels); + + int song_length = s16(&xm.header->song_length); + state.song_length = song_length; + printf("song_length: %d\n", song_length); + + //for (int i = 0; i < song_length; i++) { + //printf(" %x\n", xm.header->pattern_order_table[i]); + //} } void wait() @@ -318,7 +357,7 @@ void debug_note(interpreter_state& state, int ch, xm_pattern_format_t * pf) if (ch == 7) { printf("%3d %3d |", state.pattern_index, state.line_index); - for (int i = 0; i < 8; i++) + for (int i = 0; i < state.number_of_channels; i++) printf(" %2d %2d %2x%02x |", column[i].note, column[i].instrument, @@ -348,6 +387,12 @@ void _play_note(int ch, xm_pattern_format_t * pf) int lpctl = (loop_type == 0) ? 0 : 1; int lsa = s32(&sample_header->sample_loop_start) / bytes_per_sample; int len = s32(&sample_header->sample_loop_length) / bytes_per_sample; + if (len == 0) { + len = s32(&sample_header->sample_length) / bytes_per_sample; + } + if (len >= 65535) { + len = 65532; + } assert(start >= 0); assert(lsa >= 0); assert(len >= 0); @@ -376,8 +421,8 @@ void _play_note(int ch, xm_pattern_format_t * pf) wait(); aica_sound.channel[ch].PCMS(pcms); wait(); aica_sound.channel[ch].SA(start); wait(); aica_sound.channel[ch].LPCTL(lpctl); - wait(); aica_sound.channel[ch].LSA(lsa); - wait(); aica_sound.channel[ch].LEA(lsa + len); + wait(); aica_sound.channel[ch].LSA((lsa) & ~(0b11)); + wait(); aica_sound.channel[ch].LEA((lsa + len) & ~(0b11)); wait(); aica_sound.channel[ch].oct_fns = note_to_oct_fns(pf->note + sample_header->relative_note_number); wait(); aica_sound.channel[ch].DISDL(disdl); wait(); aica_sound.channel[ch].KYONB(1); @@ -446,7 +491,7 @@ int parse_pattern_line(interpreter_state& state, xm_pattern_header_t * pattern_h { uint8_t * pattern = (uint8_t *)(((int)pattern_header) + s32(&pattern_header->pattern_header_length)); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < state.number_of_channels; i++) { int p = pattern[note_offset]; if (p & 0x80) { note_offset += 1; @@ -477,21 +522,443 @@ void next_pattern(interpreter_state& state, int pattern_break) state.next_note_offset = 0; state.pattern_break = -1; - state.pattern_index += 1; - printf("pattern_index: %d\n", state.pattern_index); - if (state.pattern_index >= 0xe) - state.pattern_index = 1; + state.pattern_order_table_index += 1; + printf("pattern_order_table_index: %d\n", state.pattern_order_table_index); + if (state.pattern_order_table_index >= state.song_length) + state.pattern_order_table_index = 0; + state.pattern_index = xm.header->pattern_order_table[state.pattern_order_table_index]; +} + +void vbr100() +{ + serial::string("vbr100\n"); + interrupt_exception(); +} + +void vbr400() +{ + serial::string("vbr400\n"); + interrupt_exception(); +} + +constexpr int div(int n, int d) +{ + return (n + 32 - 1) / 32; +} + +struct framebuffer { + int px_width; + int px_height; + + framebuffer(int width, int height) + : px_width(width), px_height(height) + {} + + int tile_width() { + return div(px_width, 32); + } + int tile_height() { + return div(px_height, 32); + } +}; +struct framebuffer framebuffer(640, 480); +const int bytes_per_pixel = 2; + +constexpr uint32_t ta_alloc = 0 + | ta_alloc_ctrl::pt_opb::no_list + | ta_alloc_ctrl::tm_opb::no_list + | ta_alloc_ctrl::t_opb::no_list + | ta_alloc_ctrl::om_opb::no_list + | ta_alloc_ctrl::o_opb::_32x4byte; + +constexpr int ta_cont_count = 1; +constexpr struct opb_size opb_size[ta_cont_count] = { + { + .opaque = 32 * 4, + .opaque_modifier = 0, + .translucent = 0, + .translucent_modifier = 0, + .punch_through = 0 + } +}; + +static volatile int ta_in_use = 0; +static volatile int core_in_use = 0; +static volatile int next_frame = 0; +static volatile int framebuffer_ix = 0; +static volatile int next_frame_ix = 0; + +static inline void pump_events(uint32_t istnrm) +{ + if (istnrm & istnrm::v_blank_in) { + system.ISTNRM = istnrm::v_blank_in; + + next_frame = 1; + holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[next_frame_ix].start; + } + + if (istnrm & istnrm::end_of_render_tsp) { + system.ISTNRM = istnrm::end_of_render_tsp + | istnrm::end_of_render_isp + | istnrm::end_of_render_video; + + next_frame_ix = framebuffer_ix; + framebuffer_ix += 1; + if (framebuffer_ix >= 3) framebuffer_ix = 0; + + core_in_use = 0; + } + + if (istnrm & istnrm::end_of_transferring_opaque_list) { + system.ISTNRM = istnrm::end_of_transferring_opaque_list; + + core_in_use = 1; + core_start_render2(texture_memory_alloc.region_array.start, + texture_memory_alloc.isp_tsp_parameters.start, + texture_memory_alloc.background[0].start, + texture_memory_alloc.framebuffer[framebuffer_ix].start, + framebuffer.px_width); + + ta_in_use = 0; + } +} + +static inline void tmu0_events() +{ + xm_pattern_header_t * pattern_header = xm.pattern_header[state.pattern_index]; + int pattern_data_size = s16(&pattern_header->packed_pattern_data_size); + + 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); + if (keyoff_tick) { + // execute keyoffs + parse_pattern_line(state, pattern_header, state.next_note_offset, rekey_note); + wait(); aica_sound.channel[0].KYONEX(1); + } + + if (state.pattern_break >= 0 && pattern_break_tick) { + printf("pattern_break\n"); + next_pattern(state, -1); + } + + if (note_tick) { + state.note_offset = state.next_note_offset; + state.next_note_offset = parse_pattern_line(state, pattern_header, state.note_offset, play_debug_note); + //state.next_note_offset = parse_pattern_line(state, pattern_header, state.note_offset, play_note); + state.line_index += 1; + wait(); aica_sound.channel[0].KYONEX(1); + } + if (effect_tick && !note_tick) { + // execute effects + parse_pattern_line(state, pattern_header, state.note_offset, play_note_effect); + wait(); aica_sound.channel[0].KYONEX(1); + } + + if (state.next_note_offset >= pattern_data_size && pattern_break_tick) { + printf("pattern_data_size\n"); + next_pattern(state, -1); + } + + state.tick += 1; +} + +void vbr600() +{ + uint32_t sr; + asm volatile ("stc sr,%0" : "=r" (sr)); + sr |= sh::sr::imask(15); + asm volatile ("ldc %0,sr" : : "r" (sr)); + + if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x320) { // Holly + uint32_t istnrm = system.ISTNRM; + uint32_t isterr = system.ISTERR; + + if (isterr) { + serial::string("isterr: "); + serial::integer(system.ISTERR); + } + + pump_events(istnrm); + } else if (sh7091.CCN.EXPEVT == 0 && sh7091.CCN.INTEVT == 0x400) { // TMU0 + sh7091.TMU.TCR0 + = tmu::tcr0::UNIE + | tmu::tcr0::tpsc::p_phi_256; // clear underflow + + tmu0_events(); + } else { + serial::string("vbr600\n"); + interrupt_exception(); + } + + sr &= ~sh::sr::imask(15); + asm volatile ("ldc %0,sr" : : "r" (sr)); +} + +void framebuffer_init() +{ + int x_size = framebuffer.px_width; + int y_size = framebuffer.px_height; + + // write + + holly.FB_X_CLIP = fb_x_clip::fb_x_clip_max(x_size - 1) + | fb_x_clip::fb_x_clip_min(0); + + holly.FB_Y_CLIP = fb_y_clip::fb_y_clip_max(y_size - 1) + | fb_y_clip::fb_y_clip_min(0); + + // read + + holly.FB_R_SIZE = fb_r_size::fb_modulus(1) + | fb_r_size::fb_y_size(y_size - 1) + | fb_r_size::fb_x_size((x_size * bytes_per_pixel) / 4 - 1); + + holly.FB_R_CTRL = fb_r_ctrl::vclk_div::pclk_vclk_1 + | fb_r_ctrl::fb_depth::_565_rgb_16bit + | fb_r_ctrl::fb_enable; +} + +void scaler_init() +{ + holly.Y_COEFF = y_coeff::coefficient_1(0x80) + | y_coeff::coefficient_0_2(0x40); + + // in 6.10 fixed point; 0x0400 is 1x vertical scale + holly.SCALER_CTL = scaler_ctl::vertical_scale_factor(0x0400); + + holly.FB_BURSTCTRL = fb_burstctrl::wr_burst(0x09) + | fb_burstctrl::vid_lat(0x3f) + | fb_burstctrl::vid_burst(0x39); +} + +void spg_set_mode_720x480() +{ + holly.SPG_CONTROL + = spg_control::sync_direction::output; + + holly.SPG_LOAD + = spg_load::vcount(525 - 1) // number of lines per field + | spg_load::hcount(858 - 1); // number of video clock cycles per line + + holly.SPG_HBLANK + = spg_hblank::hbend(117) // H Blank ending position + | spg_hblank::hbstart(837); // H Blank starting position + + holly.SPG_VBLANK + = spg_vblank::vbend(40) // V Blank ending position + | spg_vblank::vbstart(520); // V Blank starting position + + holly.SPG_WIDTH + = spg_width::eqwidth(16 - 1) // Specify the equivalent pulse width (number of video clock cycles - 1) + | spg_width::bpwidth(794 - 1) // Specify the broad pulse width (number of video clock cycles - 1) + | spg_width::vswidth(3) // V Sync width (number of lines) + | spg_width::hswidth(64 - 1); // H Sync width (number of video clock cycles - 1) + + holly.VO_STARTX + = vo_startx::horizontal_start_position(117); + + holly.VO_STARTY + = vo_starty::vertical_start_position_on_field_2(40) + | vo_starty::vertical_start_position_on_field_1(40); + + holly.VO_CONTROL + = vo_control::pclk_delay(22); + + holly.SPG_HBLANK_INT + = spg_hblank_int::line_comp_val(837); + + holly.SPG_VBLANK_INT + = spg_vblank_int::vblank_out_interrupt_line_number(21) + | spg_vblank_int::vblank_in_interrupt_line_number(520); +} + +void spg_set_mode_640x480() +{ + holly.SPG_CONTROL + = spg_control::sync_direction::output; + + holly.SPG_LOAD + = spg_load::vcount(525 - 1) // number of lines per field + | spg_load::hcount(858 - 1); // number of video clock cycles per line + + holly.SPG_HBLANK + = spg_hblank::hbend(126) // H Blank ending position + | spg_hblank::hbstart(837); // H Blank starting position + + holly.SPG_VBLANK + = spg_vblank::vbend(40) // V Blank ending position + | spg_vblank::vbstart(520); // V Blank starting position + + holly.SPG_WIDTH + = spg_width::eqwidth(16 - 1) // Specify the equivalent pulse width (number of video clock cycles - 1) + | spg_width::bpwidth(794 - 1) // Specify the broad pulse width (number of video clock cycles - 1) + | spg_width::vswidth(3) // V Sync width (number of lines) + | spg_width::hswidth(64 - 1); // H Sync width (number of video clock cycles - 1) + + holly.VO_STARTX + = vo_startx::horizontal_start_position(168); + + holly.VO_STARTY + = vo_starty::vertical_start_position_on_field_2(40) + | vo_starty::vertical_start_position_on_field_1(40); + + holly.VO_CONTROL + = vo_control::pclk_delay(22); + + holly.SPG_HBLANK_INT + = spg_hblank_int::line_comp_val(837); + + holly.SPG_VBLANK_INT + = spg_vblank_int::vblank_out_interrupt_line_number(21) + | spg_vblank_int::vblank_in_interrupt_line_number(520); +} + +void core_param_init() +{ + uint32_t region_array_start = texture_memory_alloc.region_array.start; + uint32_t isp_tsp_parameters_start = texture_memory_alloc.isp_tsp_parameters.start; + uint32_t background_start = texture_memory_alloc.framebuffer[0].start; + + holly.REGION_BASE = region_array_start; + holly.PARAM_BASE = isp_tsp_parameters_start; + + uint32_t background_offset = background_start - isp_tsp_parameters_start; + + holly.ISP_BACKGND_T + = isp_backgnd_t::tag_address(background_offset / 4) + | isp_backgnd_t::tag_offset(0) + | isp_backgnd_t::skip(1); + holly.ISP_BACKGND_D = _i(1.f/100000.f); + + holly.FB_W_CTRL + = fb_w_ctrl::fb_dither + | fb_w_ctrl::fb_packmode::_565_rgb_16bit; + + holly.FB_W_LINESTRIDE = (framebuffer.px_width * bytes_per_pixel) / 8; +} + +void graphics_init() +{ + holly.SOFTRESET = softreset::pipeline_soft_reset + | softreset::ta_soft_reset; + holly.SOFTRESET = 0; + + scaler_init(); + core_init(); + core_param_init(); + spg_set_mode_640x480(); + framebuffer_init(); + + background_parameter2(texture_memory_alloc.framebuffer[0].start, + 0xff800080); + + region_array_multipass(framebuffer.tile_width(), + framebuffer.tile_height(), + opb_size, + ta_cont_count, + texture_memory_alloc.region_array.start, + texture_memory_alloc.object_list.start); +} + +void global_polygon_type_0(ta_parameter_writer& writer) +{ + const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume + | para_control::list_type::opaque + | obj_control::col_type::packed_color + | obj_control::gouraud; + + const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater + | isp_tsp_instruction_word::culling_mode::no_culling; + + const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::fog_control::no_fog; + + writer.append() = + ta_global_parameter::polygon_type_0(parameter_control_word, + isp_tsp_instruction_word, + tsp_instruction_word, + 0, + 0, // data_size_for_sort_dma + 0 // next_address_for_sort_dma + ); +} + +struct vertex { + vec3 p; + uint32_t c; +}; + +static inline void triangle(ta_parameter_writer& writer, + const vertex& a, const vertex& b, const vertex& c) +{ + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false), + a.p.x, a.p.y, a.p.z, + a.c); + + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false), + b.p.x, b.p.y, b.p.z, + b.c); + + writer.append() = + ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(true), + c.p.x, c.p.y, c.p.z, + c.c); +} + +const vertex triangle_vertices[] = { + { { 320.000f, 50.f, 0.1f }, 0xffff0000 }, + { { 539.393f, 430.f, 0.1f }, 0xff00ff00 }, + { { 100.607f, 430.f, 0.1f }, 0xff0000ff }, +}; + +void transfer_scene(ta_parameter_writer& writer) +{ + global_polygon_type_0(writer); + + triangle(writer, triangle_vertices[0], triangle_vertices[1], triangle_vertices[2]); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); +} + +void graphics_event(ta_parameter_writer& writer) +{ + writer.offset = 0; + + transfer_scene(writer); + + while (ta_in_use); + while (core_in_use); + ta_in_use = 1; + ta_polygon_converter_init2(texture_memory_alloc.isp_tsp_parameters.start, + texture_memory_alloc.isp_tsp_parameters.end, + texture_memory_alloc.object_list.start, + texture_memory_alloc.object_list.end, + opb_size[0].total(), + ta_alloc, + framebuffer.tile_width(), + framebuffer.tile_height()); + ta_polygon_converter_writeback(writer.buf, writer.offset); + ta_polygon_converter_transfer(writer.buf, writer.offset); + + while (next_frame == 0); + next_frame = 0; } uint8_t __attribute__((aligned(32))) zero[0x28c0] = {}; -void main() +void sound_init() { - serial::init(0); - - int buf = (int)&_binary_xm_milkypack01_xm_start; + //int buf = (int)&_binary_xm_milkypack01_xm_start; //int buf = (int)&_binary_xm_middle_c_xm_start; //int buf = (int)&_binary_xm_test_xm_start; + //int buf = (int)&_binary_xm_xmtest_xm_start; + int buf = (int)&_binary_xm_catch_this_rebel_xm_start; xm_init(buf); wait(); aica_sound.common.vreg_armrst = aica::vreg_armrst::ARMRST(1); @@ -552,10 +1019,10 @@ void main() wait(); aica_sound.channel[i].PCMS(0); wait(); aica_sound.channel[i].LSA(0); wait(); aica_sound.channel[i].LEA(0); - wait(); aica_sound.channel[i].D2R(0x1); - wait(); aica_sound.channel[i].D1R(0x1); - wait(); aica_sound.channel[i].RR(0xc); - wait(); aica_sound.channel[i].AR(0x1c); + wait(); aica_sound.channel[i].D2R(0); + wait(); aica_sound.channel[i].D1R(0); + wait(); aica_sound.channel[i].RR(0x1f); + wait(); aica_sound.channel[i].AR(0x1f); wait(); aica_sound.channel[i].ALFOS(0); wait(); aica_sound.channel[i].PLFOS(0); @@ -574,7 +1041,7 @@ void main() aica::mono_mem8mb_dac18b_ver_mvol::MONO(0) // enable panpots | aica::mono_mem8mb_dac18b_ver_mvol::MEM8MB(0) // 16Mbit SDRAM | aica::mono_mem8mb_dac18b_ver_mvol::DAC18B(0) // 16-bit DAC - | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xf) // 15/15 volume + | aica::mono_mem8mb_dac18b_ver_mvol::MVOL(0xc) // volume ; // 195 = 1ms @@ -582,13 +1049,12 @@ void main() printf("default_bpm %d\n", xm.header->default_bpm); printf("default_tempo %d\n", xm.header->default_tempo); - struct interpreter_state state; - state.tick_rate = 195.32 * 2500 / xm.header->default_bpm; state.ticks_per_line = xm.header->default_tempo; state.tick = 0; state.pattern_break = -1; - state.pattern_index = 0x1; + state.pattern_order_table_index = 0; + state.pattern_index = xm.header->pattern_order_table[state.pattern_order_table_index]; state.line_index = 0; state.note_offset = 0; state.next_note_offset = 0; @@ -600,53 +1066,31 @@ void main() sh7091.TMU.TSTR = 0; // stop all timers sh7091.TMU.TCOR0 = state.tick_rate / 2; sh7091.TMU.TOCR = tmu::tocr::tcoe::tclk_is_external_clock_or_input_capture; - sh7091.TMU.TCR0 = tmu::tcr0::tpsc::p_phi_256; // 256 / 50MHz = 5.12 μs ; underflows in ~1 hour + sh7091.TMU.TCR0 + = tmu::tcr0::UNIE + | tmu::tcr0::tpsc::p_phi_256; // 256 / 50MHz = 5.12 μs ; underflows in ~1 hour sh7091.TMU.TCNT0 = 0; sh7091.TMU.TSTR = tmu::tstr::str0::counter_start; - while (1) { - xm_pattern_header_t * pattern_header = xm.pattern_header[state.pattern_index]; - int pattern_data_size = s16(&pattern_header->packed_pattern_data_size); - - while ((sh7091.TMU.TCR0 & tmu::tcr0::UNF) == 0) { - } - sh7091.TMU.TCR0 = tmu::tcr0::tpsc::p_phi_256; // clear underflow - - 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); - if (keyoff_tick) { - // execute keyoffs - parse_pattern_line(state, pattern_header, state.next_note_offset, rekey_note); - wait(); aica_sound.channel[0].KYONEX(1); - } - - if (state.pattern_break >= 0 && pattern_break_tick) { - printf("pattern_break\n"); - next_pattern(state, -1); - } - - if (note_tick) { - state.note_offset = state.next_note_offset; - state.next_note_offset = parse_pattern_line(state, pattern_header, state.note_offset, play_debug_note); - //state.next_note_offset = parse_pattern_line(state, pattern_header, state.note_offset, play_note); - state.line_index += 1; - wait(); aica_sound.channel[0].KYONEX(1); - } - if (effect_tick && !note_tick) { - // execute effects - parse_pattern_line(state, pattern_header, state.note_offset, play_note_effect); - wait(); aica_sound.channel[0].KYONEX(1); - } - - if (state.next_note_offset >= pattern_data_size && pattern_break_tick) { - printf("pattern_data_size\n"); - next_pattern(state, -1); - } - - state.tick += 1; - } - - while (1); + sh7091.INTC.IPRA = intc::ipra::TMU0(1); +} + +void main() +{ + serial::init(0); + + sound_init(); + graphics_init(); + interrupt_init(); + + system.IML6NRM = istnrm::end_of_render_tsp + | istnrm::v_blank_in + | istnrm::end_of_transferring_opaque_list; + + 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))); + + while (1) { + graphics_event(writer); + } } diff --git a/xm/catch_this_rebel.xm b/xm/catch_this_rebel.xm new file mode 100644 index 0000000..cad71a0 Binary files /dev/null and b/xm/catch_this_rebel.xm differ diff --git a/xm/catch_this_rebel.xm.h b/xm/catch_this_rebel.xm.h new file mode 100644 index 0000000..56375b7 --- /dev/null +++ b/xm/catch_this_rebel.xm.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_xm_catch_this_rebel_xm_start __asm("_binary_xm_catch_this_rebel_xm_start"); +extern uint32_t _binary_xm_catch_this_rebel_xm_end __asm("_binary_xm_catch_this_rebel_xm_end"); +extern uint32_t _binary_xm_catch_this_rebel_xm_size __asm("_binary_xm_catch_this_rebel_xm_size"); + +#ifdef __cplusplus +} +#endif diff --git a/xm/xmtest.xm b/xm/xmtest.xm new file mode 100644 index 0000000..301aad7 Binary files /dev/null and b/xm/xmtest.xm differ diff --git a/xm/xmtest.xm.h b/xm/xmtest.xm.h new file mode 100644 index 0000000..346170c --- /dev/null +++ b/xm/xmtest.xm.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t _binary_xm_xmtest_xm_start __asm("_binary_xm_xmtest_xm_start"); +extern uint32_t _binary_xm_xmtest_xm_end __asm("_binary_xm_xmtest_xm_end"); +extern uint32_t _binary_xm_xmtest_xm_size __asm("_binary_xm_xmtest_xm_size"); + +#ifdef __cplusplus +} +#endif