diff --git a/src/framebuffer.cpp b/src/framebuffer.cpp new file mode 100644 index 0000000..d7b6814 --- /dev/null +++ b/src/framebuffer.cpp @@ -0,0 +1,149 @@ +#include "holly/holly.hpp" +#include "holly/core_bits.hpp" +#include "holly/texture_memory_alloc9.hpp" + +#include "framebuffer.hpp" + +struct framebuffer framebuffer(640, 480); + +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_packmode::_565_rgb_16bit; + + holly.FB_W_LINESTRIDE = (framebuffer.px_width * bytes_per_pixel) / 8; +} diff --git a/src/framebuffer.hpp b/src/framebuffer.hpp index 901168d..cb91db3 100644 --- a/src/framebuffer.hpp +++ b/src/framebuffer.hpp @@ -1,6 +1,6 @@ -const int bytes_per_pixel = 2; +#pragma once -constexpr int div(int n, int d) +constexpr inline int div(int n, int d) { return (n + 32 - 1) / 32; } @@ -20,146 +20,13 @@ struct framebuffer { return div(px_height, 32); } }; -struct framebuffer framebuffer(640, 480); -void framebuffer_init() -{ - int x_size = framebuffer.px_width; - int y_size = framebuffer.px_height; +const int bytes_per_pixel = 2; - // write +extern struct framebuffer framebuffer; - 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_packmode::_565_rgb_16bit; - - holly.FB_W_LINESTRIDE = (framebuffer.px_width * bytes_per_pixel) / 8; -} +void framebuffer_init(); +void scaler_init(); +void spg_set_mode_720x480(); +void spg_set_mode_640x480(); +void core_param_init(); diff --git a/src/graphics.cpp b/src/graphics.cpp index d517364..394b38d 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -24,14 +24,8 @@ #include "font/tandy1k.data.h" -#include "math/float_types.hpp" - -#include "printf/unparse.h" - -#include "ta_parameter.hpp" - #include "framebuffer.hpp" -#include "interpreter.hpp" +#include "src/tracker_scene/scene.hpp" constexpr uint32_t ta_alloc = 0 | ta_alloc_ctrl::pt_opb::_32x4byte @@ -169,545 +163,11 @@ void graphics_init() transfer_palettes(); } -struct vertex { - vec3 p; - vec2 t; -}; - -const vertex quad_vertices[] = { - { { 0, 0, 0.001f }, {0, 0} }, - { { 1, 0, 0.001f }, {1, 0} }, - { { 1, 1, 0.001f }, {1, 1} }, - { { 0, 1, 0.001f }, {0, 1} }, -}; - -const int texture_width = 128; -const int texture_height = 256; -const int glyph_width = 9; -const int glyph_height = 12; -const int glyphs_per_row = texture_width / glyph_width; -const int glyph_hori_advance = 8; -const int glyph_vert_advance = 9; - -static inline vec2 transform_glyph_texture(const vec2& t, int char_code) -{ - int row = char_code / glyphs_per_row; - int col = char_code % glyphs_per_row; - - return { - (float)(col * glyph_width + t.x * glyph_width) / (float)(texture_width), - (float)(row * glyph_height + t.y * glyph_height) / (float)(texture_height), - }; -} - -static inline vec3 transform_glyph_position(const vec3& p, float x, float y) -{ - return { - p.x * glyph_width + x, - p.y * glyph_height + y, - p.z - }; -} - -void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y, int base_color) -{ - vec3 ap = transform_glyph_position(quad_vertices[0].p, x, y); - vec3 bp = transform_glyph_position(quad_vertices[1].p, x, y); - vec3 cp = transform_glyph_position(quad_vertices[2].p, x, y); - vec3 dp = transform_glyph_position(quad_vertices[3].p, x, y); - - vec2 at = transform_glyph_texture(quad_vertices[0].t, c); - vec2 bt = transform_glyph_texture(quad_vertices[1].t, c); - vec2 ct = transform_glyph_texture(quad_vertices[2].t, c); - vec2 dt = transform_glyph_texture(quad_vertices[3].t, c); - - quad_type_3(writer, - ap, at, - bp, bt, - cp, ct, - dp, dt, - base_color); -} - -int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y, - int base_color) -{ - const uint8_t * u8 = (const uint8_t *)s; - int len = 0; - while (*u8) { - len += 1; - transfer_glyph(writer, *u8++, x, y, base_color); - x += glyph_hori_advance; - } - return len; -} - -int transfer_integer(ta_parameter_writer& writer, int n, int x, int y, - int length, int fill, - int base_color) -{ - char buf[16]; - - int len = unparse_base10(buf, n, length, fill); - buf[len] = 0; - - transfer_string(writer, buf, x, y, base_color); - - return len; -} - -int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y, - int length, int fill, - int base_color) -{ - char buf[16]; - - int len = unparse_base16(buf, n, length, fill); - buf[len] = 0; - - transfer_string(writer, buf, x, y, base_color); - - return len; -} - -const char note_names[12][2] = { - {'C', '-'}, - {'C', '#'}, - {'D', '-'}, - {'D', '#'}, - - {'E', '-'}, - {'F', '-'}, - {'F', '#'}, - {'G', '-'}, - - {'G', '#'}, - {'A', '-'}, - {'A', '#'}, - {'B', '-'}, -}; - -const int horizontal_bar = 0x16; -const int interpunct = 0xb7; - -int transfer_fill(ta_parameter_writer& writer, int count, int x, int y, - int base_color) -{ - for (int i = 0; i < count; i++) { - transfer_glyph(writer, interpunct, x, y, base_color); - x += glyph_hori_advance; - } - return x; -} - -static inline int effect_type_char(int effect_type) -{ - if (effect_type >= 0 && effect_type <= 9) - return effect_type + '0'; - if (effect_type >= 10 && effect_type <= 36) - return (effect_type - 10) + 'a'; - return 128; -} - -static inline int transfer_note(ta_parameter_writer& writer, int note, int x, int y) -{ - int base_color = 0xffffff; - - if (note == 97) { - transfer_glyph(writer, horizontal_bar, x, y, base_color); - x += glyph_hori_advance; - transfer_glyph(writer, horizontal_bar, x, y, base_color); - x += glyph_hori_advance; - transfer_glyph(writer, horizontal_bar, x, y, base_color); - x += glyph_hori_advance; - } else if (note != 0) { - int c0_note = note - 1; - const char * note_name = note_names[c0_note % 12]; - int octave = c0_note / 12; - transfer_glyph(writer, note_name[0], x, y, base_color); - x += glyph_hori_advance; - transfer_glyph(writer, note_name[1], x, y, base_color); - x += glyph_hori_advance; - transfer_glyph(writer, '0' + octave, x, y, base_color); - x += glyph_hori_advance; - } else { - x = transfer_fill(writer, 3, x, y, base_color); - } - return x; -} - -static inline int transfer_instrument(ta_parameter_writer& writer, int instrument, int x, int y) -{ - int base_color = 0x9393ff; - - if (instrument != 0) { - int len = transfer_hex_integer(writer, instrument, x, y, 2, interpunct, base_color); - x += glyph_hori_advance * len; - } else { - x = transfer_fill(writer, 2, x, y, base_color); - } - return x; -} - -static inline int transfer_volume_column_byte(ta_parameter_writer& writer, int volume_column_byte, int x, int y) -{ - int base_color = 0xa7c9f1; - - if (volume_column_byte != 0) { - int len = transfer_hex_integer(writer, volume_column_byte, x, y, 2, interpunct, base_color); - x += glyph_hori_advance * len; - } else { - x = transfer_fill(writer, 2, x, y, base_color); - } - return x; -} - -static inline int transfer_effect_type(ta_parameter_writer& writer, int effect_type, int x, int y) -{ - int base_color = 0xffffff; - - if (effect_type != 0) { - int c = effect_type_char(effect_type); - transfer_glyph(writer, c, x, y, base_color); - x += glyph_hori_advance; - } else { - x = transfer_fill(writer, 1, x, y, base_color); - } - return x; -} - -static inline int transfer_effect_parameter(ta_parameter_writer& writer, int effect_parameter, int x, int y) -{ - int base_color = 0x7f7f80; - - if (effect_parameter != 0) { - int len = transfer_hex_integer(writer, effect_parameter, x, y, 2, interpunct, base_color); - x += glyph_hori_advance * len; - } else { - x = transfer_fill(writer, 2, x, y, base_color); - } - return x; -} - -static inline int transfer_line_index(ta_parameter_writer& writer, int line_index, int x, int y) -{ - const int dark = 0x5d646b; - const int light = 0xa7a7a7; - - int base_color = ((line_index % 4) == 0) ? dark : light; - - int len = transfer_integer(writer, line_index, x, y, 2, ' ', base_color); - x += glyph_hori_advance * len; - - return x; -} - -void transfer_line(ta_parameter_writer& writer, int line_index, int x, int y) -{ - using namespace interpreter; - - x += 3; - x += 1; - x = transfer_line_index(writer, line_index, x, y); - x += 1; - x += 3; - - int line_pattern_index = line_index * state.xm.number_of_channels; - const xm_pattern_format_t * pattern = state.xm.pattern[state.pattern_index]; - for (int ch = 0; ch < state.xm.number_of_channels; ch++) { - const xm_pattern_format_t& pf = pattern[line_pattern_index + ch]; - - x += 1; - x = transfer_note(writer, pf.note, x, y); - x += 1; - x = transfer_instrument(writer, pf.instrument, x, y); - x += 1; - x = transfer_volume_column_byte(writer, pf.volume_column_byte, x, y); - x += 1; - x = transfer_effect_type(writer, pf.effect_type, x, y); - x += 1; - x = transfer_effect_parameter(writer, pf.effect_parameter, x, y); - x += 1; - - x += 3; - } -} - -void transfer_vertical_border(ta_parameter_writer& writer, float x, float y, int length) -{ - quad_type_0(writer, - {x + 0, y + 0, 1.0/7.0}, - {x + 1, y + 0, 1.0/7.0}, - {x + 1, y + length, 1.0/7.0}, - {x + 0, y + length, 1.0/7.0}, - 0x2a3536); - - quad_type_0(writer, - {x + 1, y + 0, 1.0/5.0}, - {x + 2, y + 0, 1.0/5.0}, - {x + 2, y + length, 1.0/5.0}, - {x + 1, y + length, 1.0/5.0}, - 0x202829); - - quad_type_0(writer, - {x + 2, y + 0, 1.0/10.0}, - {x + 3, y + 0, 1.0/10.0}, - {x + 3, y + length, 1.0/10.0}, - {x + 2, y + length, 1.0/10.0}, - 0x101414); -} - -void transfer_horizontal_border(ta_parameter_writer& writer, float x, float y, int length) -{ - quad_type_0(writer, - {x + 0, y + 0, 1.0/7.0}, - {x + 0, y + 1, 1.0/7.0}, - {x + length, y + 1, 1.0/7.0}, - {x + length, y + 0, 1.0/7.0}, - 0x2a3536); - - quad_type_0(writer, - {x + 0, y + 1, 1.0/5.0}, - {x + 0, y + 2, 1.0/5.0}, - {x + length, y + 2, 1.0/5.0}, - {x + length, y + 1, 1.0/5.0}, - 0x202829); - - quad_type_0(writer, - {x + 0, y + 2, 1.0/10.0}, - {x + 0, y + 3, 1.0/10.0}, - {x + length, y + 3, 1.0/10.0}, - {x + length, y + 2, 1.0/10.0}, - 0x101414); -} - -const int line_column_total_advance = (3 + 2 + 2 + 1 + 2) * glyph_hori_advance; -const int line_column_width = line_column_total_advance + 6 + 3; -const int line_rows_half = 15; -const int line_rows = line_rows_half * 2 + 1; -const int line_column_height = line_rows * glyph_vert_advance + 3 + 1; - -void transfer_borders(ta_parameter_writer& writer, int x, int y) -{ - using namespace interpreter; - - int x0 = x; - - transfer_vertical_border(writer, x, y, line_column_height); - x += 3 + glyph_hori_advance * 2 + 2; - - for (int ch = 0; ch < (state.xm.number_of_channels); ch++) { - transfer_vertical_border(writer, x, y, line_column_height); - x += line_column_width; - } - transfer_vertical_border(writer, x, y, line_column_height); - - transfer_horizontal_border(writer, x0, y, - x - x0); - - transfer_horizontal_border(writer, x0, y + line_column_height, - x - x0); -} - -void transfer_lines(ta_parameter_writer& writer, int x, int y) -{ - using namespace interpreter; - - y += 3 + 1; - - int pattern_line_count = state.xm.pattern_note_count[state.pattern_index] / state.xm.number_of_channels; - for (int i = 0; i < line_rows; i++) { - int line_ix = state.line_index - line_rows_half + i; - if (line_ix >= 0 && line_ix < pattern_line_count) - transfer_line(writer, line_ix, x, y); - y += glyph_vert_advance; - } -} - -void transfer_middle_line(ta_parameter_writer& writer, float x, float y) -{ - using namespace interpreter; - - int middle_width = line_column_width * (state.xm.number_of_channels) + (2 * glyph_hori_advance) + 2 + 3; - int middle_height = glyph_vert_advance - 1; - - y += 3; - - y += glyph_vert_advance * line_rows_half; - - quad_type_0(writer, - {x + 0, y + 0, 1.0/15.0}, - {x + 0, y + 1, 1.0/15.0}, - {x + middle_width, y + 1, 1.0/15.0}, - {x + middle_width, y + 0, 1.0/15.0}, - 0x555555); - - y += 1; - - quad_type_0(writer, - {x + 0, y + 0, 1.0/15.0}, - {x + 0, y + middle_height, 1.0/15.0}, - {x + middle_width, y + middle_height, 1.0/15.0}, - {x + middle_width, y + 0, 1.0/15.0}, - 0x404040); - - y += middle_width; - - quad_type_0(writer, - {x + 0, y + 0, 1.0/15.0}, - {x + 0, y + 1, 1.0/15.0}, - {x + middle_width, y + 1, 1.0/15.0}, - {x + middle_width, y + 0, 1.0/15.0}, - 0x202020); -} - -static inline int round_up_div(int n, int m) -{ - int div = n / m; - int rem = n % m; - if (rem == 0) - return div; - return div + 1; -} - -static inline int round_up(int n, int m) -{ - int rem = n % m; - if (rem == 0) - return n; - return n + m - rem; -} - -void transfer_rectangle(ta_parameter_writer& writer, - float x, float y, float z, - float width, float height, - uint32_t base_color) -{ - quad_type_0(writer, - {x + 0, y + 0, z}, - {x + width, y + 0, z}, - {x + width, y + height, z}, - {x + 0, y + height, z}, - base_color); -} - -void transfer_channel_status(ta_parameter_writer& writer, int x, int y) -{ - using namespace interpreter; - - const int channel_status_height = 50; - - int max_channels_per_row = framebuffer.px_width / 40; - int rows = round_up_div(state.xm.number_of_channels, max_channels_per_row); - assert(rows > 0); - int number_of_channels = round_up(state.xm.number_of_channels, rows); - int channels_per_row = number_of_channels / rows; - int width_per_col = (framebuffer.px_width - 3) / channels_per_row; - int offset = (framebuffer.px_width - (width_per_col * channels_per_row)) / 2; - - int inner_width = width_per_col - 3; - - int height_per_row = channel_status_height / rows; - int vert_center = height_per_row / 2 - glyph_vert_advance / 2; - - int ch = 0; - for (int row = 0; row < rows; row++) { - int xi = x + offset - 2; - - global_polygon_untextured(writer, - para_control::list_type::opaque, - tsp_instruction_word::dst_alpha_instr::zero); - - transfer_horizontal_border(writer, xi, y, width_per_col * channels_per_row); - - for (int col = 0; col < channels_per_row; col++) { - - global_polygon_untextured(writer, - para_control::list_type::opaque, - tsp_instruction_word::dst_alpha_instr::zero); - - transfer_vertical_border(writer, xi, y, height_per_row); - - int keyon = 128 * (state.channel[ch].keyon - 224) / 16; - if (keyon < 0) keyon = 0; - uint32_t base_color = (keyon << 16) | (keyon << 8) | (keyon << 0); - transfer_rectangle(writer, - xi, y, 1.0 / 10000.0, - width_per_col, height_per_row, - base_color); - - if (ch < state.xm.number_of_channels) { - global_polygon_textured(writer, - para_control::list_type::opaque); - - int hori_center = inner_width / 2 - (glyph_hori_advance * (ch >= 10)) / 2; - transfer_integer(writer, ch, xi + hori_center, y + vert_center, - 0, 0, - 0xa7a7a7); - } - - xi += width_per_col; - ch += 1; - } - - global_polygon_untextured(writer, - para_control::list_type::opaque, - tsp_instruction_word::dst_alpha_instr::zero); - - transfer_vertical_border(writer, xi, y, height_per_row); - - y += height_per_row; - } - - int xi = x + offset - 2; - transfer_horizontal_border(writer, xi, y, width_per_col * channels_per_row); -} - -void transfer_scene(ta_parameter_writer& writer) -{ - const int x = 3; - const int y = 100; - - { // punch-through - global_polygon_textured(writer, - para_control::list_type::punch_through); - - transfer_lines(writer, x, y); - - writer.append() = - ta_global_parameter::end_of_list(para_control::para_type::end_of_list); - } - - { // translucent - global_polygon_untextured(writer, - para_control::list_type::translucent, - tsp_instruction_word::dst_alpha_instr::one); - - transfer_middle_line(writer, x, y); - - writer.append() = - ta_global_parameter::end_of_list(para_control::para_type::end_of_list); - } - - { // opaque - global_polygon_untextured(writer, - para_control::list_type::opaque, - tsp_instruction_word::dst_alpha_instr::zero); - - transfer_borders(writer, x, y); - - transfer_channel_status(writer, 0, 0); - - 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); + tracker::scene::transfer(writer); while (ta_in_use); while (core_in_use); diff --git a/src/graphics_primitive.cpp b/src/graphics_primitive.cpp new file mode 100644 index 0000000..61a64d6 --- /dev/null +++ b/src/graphics_primitive.cpp @@ -0,0 +1,159 @@ +#include "printf/unparse.h" + +#include "ta_parameter.hpp" +#include "graphics_primitive.hpp" + +struct vertex { + vec3 p; + vec2 t; +}; + +const vertex quad_vertices[] = { + { { 0, 0, 0.001f }, {0, 0} }, + { { 1, 0, 0.001f }, {1, 0} }, + { { 1, 1, 0.001f }, {1, 1} }, + { { 0, 1, 0.001f }, {0, 1} }, +}; + +static inline vec2 transform_glyph_texture(const vec2& t, int char_code) +{ + int row = char_code / glyph::row_stride; + int col = char_code % glyph::row_stride; + + return { + (float)(col * glyph::width + t.x * glyph::width) / (float)(glyph::texture_width), + (float)(row * glyph::height + t.y * glyph::height) / (float)(glyph::texture_height), + }; +} + +static inline vec3 transform_glyph_position(const vec3& p, float x, float y) +{ + return { + p.x * glyph::width + x, + p.y * glyph::height + y, + p.z + }; +} + +void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y, + int base_color) +{ + vec3 ap = transform_glyph_position(quad_vertices[0].p, x, y); + vec3 bp = transform_glyph_position(quad_vertices[1].p, x, y); + vec3 cp = transform_glyph_position(quad_vertices[2].p, x, y); + vec3 dp = transform_glyph_position(quad_vertices[3].p, x, y); + + vec2 at = transform_glyph_texture(quad_vertices[0].t, c); + vec2 bt = transform_glyph_texture(quad_vertices[1].t, c); + vec2 ct = transform_glyph_texture(quad_vertices[2].t, c); + vec2 dt = transform_glyph_texture(quad_vertices[3].t, c); + + quad_type_3(writer, + ap, at, + bp, bt, + cp, ct, + dp, dt, + base_color); +} + +int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y, + int base_color) +{ + const uint8_t * u8 = (const uint8_t *)s; + int len = 0; + while (*u8) { + len += 1; + transfer_glyph(writer, *u8++, x, y, base_color); + x += glyph::hori_advance; + } + return len; +} + +int transfer_integer(ta_parameter_writer& writer, int n, int x, int y, + int length, int fill, + int base_color) +{ + char buf[16]; + + int len = unparse_base10(buf, n, length, fill); + buf[len] = 0; + + transfer_string(writer, buf, x, y, base_color); + + return len; +} + +int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y, + int length, int fill, + int base_color) +{ + char buf[16]; + + int len = unparse_base16(buf, n, length, fill); + buf[len] = 0; + + transfer_string(writer, buf, x, y, base_color); + + return len; +} + +void transfer_rectangle(ta_parameter_writer& writer, + float x, float y, float z, + float width, float height, + int base_color) +{ + quad_type_0(writer, + {x + 0, y + 0, z}, + {x + width, y + 0, z}, + {x + width, y + height, z}, + {x + 0, y + height, z}, + base_color); +} + +void transfer_vertical_border(ta_parameter_writer& writer, float x, float y, int length) +{ + quad_type_0(writer, + {x + 0, y + 0, 1.0/7.0}, + {x + 1, y + 0, 1.0/7.0}, + {x + 1, y + length, 1.0/7.0}, + {x + 0, y + length, 1.0/7.0}, + 0x2a3536); + + quad_type_0(writer, + {x + 1, y + 0, 1.0/5.0}, + {x + 2, y + 0, 1.0/5.0}, + {x + 2, y + length, 1.0/5.0}, + {x + 1, y + length, 1.0/5.0}, + 0x202829); + + quad_type_0(writer, + {x + 2, y + 0, 1.0/10.0}, + {x + 3, y + 0, 1.0/10.0}, + {x + 3, y + length, 1.0/10.0}, + {x + 2, y + length, 1.0/10.0}, + 0x101414); +} + +void transfer_horizontal_border(ta_parameter_writer& writer, float x, float y, int length) +{ + quad_type_0(writer, + {x + 0, y + 0, 1.0/7.0}, + {x + 0, y + 1, 1.0/7.0}, + {x + length, y + 1, 1.0/7.0}, + {x + length, y + 0, 1.0/7.0}, + 0x2a3536); + + quad_type_0(writer, + {x + 0, y + 1, 1.0/5.0}, + {x + 0, y + 2, 1.0/5.0}, + {x + length, y + 2, 1.0/5.0}, + {x + length, y + 1, 1.0/5.0}, + 0x202829); + + quad_type_0(writer, + {x + 0, y + 2, 1.0/10.0}, + {x + 0, y + 3, 1.0/10.0}, + {x + length, y + 3, 1.0/10.0}, + {x + length, y + 2, 1.0/10.0}, + 0x101414); +} diff --git a/src/graphics_primitive.hpp b/src/graphics_primitive.hpp new file mode 100644 index 0000000..27f90fa --- /dev/null +++ b/src/graphics_primitive.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "holly/ta_parameter.hpp" + +namespace glyph { + constexpr int texture_width = 128; + constexpr int texture_height = 256; + constexpr int width = 9; + constexpr int height = 12; + constexpr int hori_advance = 8; + constexpr int vert_advance = 9; + constexpr int row_stride = glyph::texture_width / glyph::width; + + const int horizontal_bar = 0x16; + const int interpunct = 0xb7; +}; + +void transfer_glyph(ta_parameter_writer& writer, int c, int x, int y, + int base_color); + +int transfer_string(ta_parameter_writer& writer, const char * s, int x, int y, + int base_color); + +int transfer_integer(ta_parameter_writer& writer, int n, int x, int y, + int length, int fill, + int base_color); + +int transfer_hex_integer(ta_parameter_writer& writer, int n, int x, int y, + int length, int fill, + int base_color); + +void transfer_rectangle(ta_parameter_writer& writer, + float x, float y, float z, + float width, float height, + int base_color); + +void transfer_vertical_border(ta_parameter_writer& writer, float x, float y, int length); + +void transfer_horizontal_border(ta_parameter_writer& writer, float x, float y, int length); diff --git a/src/ta_parameter.hpp b/src/ta_parameter.hpp index a91d454..cc44f58 100644 --- a/src/ta_parameter.hpp +++ b/src/ta_parameter.hpp @@ -1,4 +1,14 @@ -void global_polygon_textured(ta_parameter_writer& writer, uint32_t list_type) +#pragma once + +#include "holly/ta_global_parameter.hpp" +#include "holly/ta_vertex_parameter.hpp" +#include "holly/ta_parameter.hpp" +#include "holly/ta_global_parameter.hpp" +#include "holly/isp_tsp.hpp" +#include "holly/texture_memory_alloc9.hpp" +#include "math/float_types.hpp" + +static inline void global_polygon_textured(ta_parameter_writer& writer, uint32_t list_type) { const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume | list_type @@ -32,7 +42,7 @@ void global_polygon_textured(ta_parameter_writer& writer, uint32_t list_type) } -void global_polygon_untextured(ta_parameter_writer& writer, uint32_t list_type, uint32_t dst_alpha) +static inline void global_polygon_untextured(ta_parameter_writer& writer, uint32_t list_type, uint32_t dst_alpha) { const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume | list_type diff --git a/src/tracker_scene/channel_status.cpp b/src/tracker_scene/channel_status.cpp new file mode 100644 index 0000000..df0d114 --- /dev/null +++ b/src/tracker_scene/channel_status.cpp @@ -0,0 +1,104 @@ +#include "../ta_parameter.hpp" + +#include "../graphics_primitive.hpp" +#include "../interpreter.hpp" +#include "../framebuffer.hpp" + +#include "channel_status.hpp" + +static inline int round_up_div(int n, int m) +{ + int div = n / m; + int rem = n % m; + if (rem == 0) + return div; + return div + 1; +} + +static inline int round_up(int n, int m) +{ + int rem = n % m; + if (rem == 0) + return n; + return n + m - rem; +} + +namespace tracker { + namespace channel_status { + +void transfer(ta_parameter_writer& writer, int x, int y) +{ + using namespace interpreter; + + const int channel_status_height = 50; + + int max_channels_per_row = framebuffer.px_width / 40; + int rows = round_up_div(state.xm.number_of_channels, max_channels_per_row); + assert(rows > 0); + int number_of_channels = round_up(state.xm.number_of_channels, rows); + int channels_per_row = number_of_channels / rows; + int width_per_col = (framebuffer.px_width - 3) / channels_per_row; + int offset = (framebuffer.px_width - (width_per_col * channels_per_row)) / 2; + + int inner_width = width_per_col - 3; + + int height_per_row = channel_status_height / rows; + int vert_center = height_per_row / 2 - glyph::vert_advance / 2; + + int ch = 0; + for (int row = 0; row < rows; row++) { + int xi = x + offset - 2; + + global_polygon_untextured(writer, + para_control::list_type::opaque, + tsp_instruction_word::dst_alpha_instr::zero); + + transfer_horizontal_border(writer, xi, y, width_per_col * channels_per_row); + + for (int col = 0; col < channels_per_row; col++) { + + global_polygon_untextured(writer, + para_control::list_type::opaque, + tsp_instruction_word::dst_alpha_instr::zero); + + transfer_vertical_border(writer, xi, y, height_per_row); + + int keyon = 128 * (state.channel[ch].keyon - 224) / 16; + if (keyon < 0) keyon = 0; + uint32_t base_color = (keyon << 16) | (keyon << 8) | (keyon << 0); + transfer_rectangle(writer, + xi, y, 1.0 / 10000.0, + width_per_col, height_per_row, + base_color); + + if (ch < state.xm.number_of_channels) { + global_polygon_textured(writer, + para_control::list_type::opaque); + + int hori_center = inner_width / 2 - (glyph::hori_advance * (ch >= 10)) / 2; + transfer_integer(writer, ch, xi + hori_center, y + vert_center, + 0, 0, + 0xa7a7a7); + } + + xi += width_per_col; + ch += 1; + } + + global_polygon_untextured(writer, + para_control::list_type::opaque, + tsp_instruction_word::dst_alpha_instr::zero); + + transfer_vertical_border(writer, xi, y, height_per_row); + + y += height_per_row; + } + + int xi = x + offset - 2; + transfer_horizontal_border(writer, xi, y, width_per_col * channels_per_row); + + //borders(writer, x, y); +} + + } +} diff --git a/src/tracker_scene/channel_status.hpp b/src/tracker_scene/channel_status.hpp new file mode 100644 index 0000000..94cc607 --- /dev/null +++ b/src/tracker_scene/channel_status.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "holly/ta_parameter.hpp" + +namespace tracker { + namespace channel_status { + void transfer(ta_parameter_writer& writer, int x, int y); + } +} diff --git a/src/tracker_scene/notes.cpp b/src/tracker_scene/notes.cpp new file mode 100644 index 0000000..085cb66 --- /dev/null +++ b/src/tracker_scene/notes.cpp @@ -0,0 +1,253 @@ +#include "../ta_parameter.hpp" + +#include "../graphics_primitive.hpp" +#include "../interpreter.hpp" + +#include "notes.hpp" + +const int line_column_total_advance = (3 + 2 + 2 + 1 + 2) * glyph::hori_advance; +const int line_column_width = line_column_total_advance + 6 + 3; +const int line_rows_half = 15; +const int line_rows = line_rows_half * 2 + 1; +const int line_column_height = line_rows * glyph::vert_advance + 3 + 1; + +static inline int transfer_line_index(ta_parameter_writer& writer, int line_index, int x, int y) +{ + const int dark = 0x5d646b; + const int light = 0xa7a7a7; + + int base_color = ((line_index % 4) == 0) ? dark : light; + + int len = transfer_integer(writer, line_index, x, y, 2, ' ', base_color); + x += glyph::hori_advance * len; + + return x; +} + +static inline int transfer_fill(ta_parameter_writer& writer, int count, int x, int y, + int base_color) +{ + for (int i = 0; i < count; i++) { + transfer_glyph(writer, glyph::interpunct, x, y, base_color); + x += glyph::hori_advance; + } + return x; +} + +static inline int transfer_note(ta_parameter_writer& writer, int note, int x, int y) +{ + static const char note_names[12][2] = { + {'C', '-'}, + {'C', '#'}, + {'D', '-'}, + {'D', '#'}, + + {'E', '-'}, + {'F', '-'}, + {'F', '#'}, + {'G', '-'}, + + {'G', '#'}, + {'A', '-'}, + {'A', '#'}, + {'B', '-'}, + }; + + int base_color = 0xffffff; + + if (note == 97) { + transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color); + x += glyph::hori_advance; + transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color); + x += glyph::hori_advance; + transfer_glyph(writer, glyph::horizontal_bar, x, y, base_color); + x += glyph::hori_advance; + } else if (note != 0) { + int c0_note = note - 1; + const char * note_name = note_names[c0_note % 12]; + int octave = c0_note / 12; + transfer_glyph(writer, note_name[0], x, y, base_color); + x += glyph::hori_advance; + transfer_glyph(writer, note_name[1], x, y, base_color); + x += glyph::hori_advance; + transfer_glyph(writer, '0' + octave, x, y, base_color); + x += glyph::hori_advance; + } else { + x = transfer_fill(writer, 3, x, y, base_color); + } + return x; +} + +static inline int transfer_instrument(ta_parameter_writer& writer, int instrument, int x, int y) +{ + int base_color = 0x9393ff; + + if (instrument != 0) { + int len = transfer_hex_integer(writer, instrument, x, y, 2, glyph::interpunct, base_color); + x += glyph::hori_advance * len; + } else { + x = transfer_fill(writer, 2, x, y, base_color); + } + return x; +} + +static inline int transfer_volume_column_byte(ta_parameter_writer& writer, int volume_column_byte, int x, int y) +{ + int base_color = 0xa7c9f1; + + if (volume_column_byte != 0) { + int len = transfer_hex_integer(writer, volume_column_byte, x, y, 2, glyph::interpunct, base_color); + x += glyph::hori_advance * len; + } else { + x = transfer_fill(writer, 2, x, y, base_color); + } + return x; +} + +static inline int effect_type_char(int effect_type) +{ + if (effect_type >= 0 && effect_type <= 9) + return effect_type + '0'; + if (effect_type >= 10 && effect_type <= 36) + return (effect_type - 10) + 'a'; + return 128; +} + +static inline int transfer_effect_type(ta_parameter_writer& writer, int effect_type, int x, int y) +{ + int base_color = 0xffffff; + + if (effect_type != 0) { + int c = effect_type_char(effect_type); + transfer_glyph(writer, c, x, y, base_color); + x += glyph::hori_advance; + } else { + x = transfer_fill(writer, 1, x, y, base_color); + } + return x; +} + +static inline int transfer_effect_parameter(ta_parameter_writer& writer, int effect_parameter, int x, int y) +{ + int base_color = 0x7f7f80; + + if (effect_parameter != 0) { + int len = transfer_hex_integer(writer, effect_parameter, x, y, 2, glyph::interpunct, + base_color); + x += glyph::hori_advance * len; + } else { + x = transfer_fill(writer, 2, x, y, base_color); + } + return x; +} + +static void transfer_line(ta_parameter_writer& writer, int line_index, int x, int y) +{ + using namespace interpreter; + + x += 3; + x += 1; + x = transfer_line_index(writer, line_index, x, y); + x += 1; + x += 3; + + int line_pattern_index = line_index * state.xm.number_of_channels; + const xm_pattern_format_t * pattern = state.xm.pattern[state.pattern_index]; + for (int ch = 0; ch < state.xm.number_of_channels; ch++) { + const xm_pattern_format_t& pf = pattern[line_pattern_index + ch]; + + x += 1; + x = transfer_note(writer, pf.note, x, y); + x += 1; + x = transfer_instrument(writer, pf.instrument, x, y); + x += 1; + x = transfer_volume_column_byte(writer, pf.volume_column_byte, x, y); + x += 1; + x = transfer_effect_type(writer, pf.effect_type, x, y); + x += 1; + x = transfer_effect_parameter(writer, pf.effect_parameter, x, y); + x += 1; + + x += 3; + } +} + +namespace tracker { + namespace notes { + +void borders(ta_parameter_writer& writer, int x, int y) +{ + using namespace interpreter; + + int x0 = x; + + transfer_vertical_border(writer, x, y, line_column_height); + x += 3 + glyph::hori_advance * 2 + 2; + + for (int ch = 0; ch < (state.xm.number_of_channels); ch++) { + transfer_vertical_border(writer, x, y, line_column_height); + x += line_column_width; + } + transfer_vertical_border(writer, x, y, line_column_height); + + transfer_horizontal_border(writer, x0, y, + x - x0); + + transfer_horizontal_border(writer, x0, y + line_column_height, + x - x0); +} + +void transfer_lines(ta_parameter_writer& writer, int x, int y) +{ + using namespace interpreter; + + y += 3 + 1; + + int pattern_line_count = state.xm.pattern_note_count[state.pattern_index] / state.xm.number_of_channels; + for (int i = 0; i < line_rows; i++) { + int line_ix = state.line_index - line_rows_half + i; + if (line_ix >= 0 && line_ix < pattern_line_count) + transfer_line(writer, line_ix, x, y); + y += glyph::vert_advance; + } +} + +void transfer_middle_line(ta_parameter_writer& writer, float x, float y) +{ + using namespace interpreter; + + int middle_width = line_column_width * (state.xm.number_of_channels) + (2 * glyph::hori_advance) + 2 + 3; + int middle_height = glyph::vert_advance - 1; + + y += 3; + + y += glyph::vert_advance * line_rows_half; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + 1, 1.0/15.0}, + {x + middle_width, y + 1, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x555555); + + y += 1; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + middle_height, 1.0/15.0}, + {x + middle_width, y + middle_height, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x404040); + + y += middle_width; + + quad_type_0(writer, + {x + 0, y + 0, 1.0/15.0}, + {x + 0, y + 1, 1.0/15.0}, + {x + middle_width, y + 1, 1.0/15.0}, + {x + middle_width, y + 0, 1.0/15.0}, + 0x202020); +} + + } +} diff --git a/src/tracker_scene/notes.hpp b/src/tracker_scene/notes.hpp new file mode 100644 index 0000000..bbf736d --- /dev/null +++ b/src/tracker_scene/notes.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "holly/ta_parameter.hpp" + +namespace tracker { + namespace notes { + + void borders(ta_parameter_writer& writer, int x, int y); + void transfer_lines(ta_parameter_writer& writer, int x, int y); + void transfer_middle_line(ta_parameter_writer& writer, float x, float y); + + } +} diff --git a/src/tracker_scene/scene.cpp b/src/tracker_scene/scene.cpp new file mode 100644 index 0000000..f54995a --- /dev/null +++ b/src/tracker_scene/scene.cpp @@ -0,0 +1,50 @@ +#include "../ta_parameter.hpp" + +#include "notes.hpp" +#include "channel_status.hpp" + +namespace tracker { + namespace scene { + +void transfer(ta_parameter_writer& writer) +{ + const int x = 3; + const int y = 100; + + { // punch-through + global_polygon_textured(writer, + para_control::list_type::punch_through); + + tracker::notes::transfer_lines(writer, x, y); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } + + { // translucent + global_polygon_untextured(writer, + para_control::list_type::translucent, + tsp_instruction_word::dst_alpha_instr::one); + + tracker::notes::transfer_middle_line(writer, x, y); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } + + { // opaque + global_polygon_untextured(writer, + para_control::list_type::opaque, + tsp_instruction_word::dst_alpha_instr::zero); + + tracker::notes::borders(writer, x, y); + + tracker::channel_status::transfer(writer, 0, 0); + + writer.append() = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + } +} + + } +} diff --git a/src/tracker_scene/scene.hpp b/src/tracker_scene/scene.hpp new file mode 100644 index 0000000..6d2d32a --- /dev/null +++ b/src/tracker_scene/scene.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace tracker { + namespace scene { + void transfer(ta_parameter_writer& writer); + } +} diff --git a/xm_player.mk b/xm_player.mk index 25153ee..73da7e7 100644 --- a/xm_player.mk +++ b/xm_player.mk @@ -21,7 +21,12 @@ XM_PLAYER_OBJ = \ src/main.o \ src/sound.o \ src/xm.o \ - src/malloc.o + src/malloc.o \ + src/framebuffer.o \ + src/graphics_primitive.o \ + src/tracker_scene/scene.o \ + src/tracker_scene/channel_status.o \ + src/tracker_scene/notes.o xm_player.elf: LDSCRIPT = $(LIB)/main.lds xm_player.elf: $(START_OBJ) $(XM_PLAYER_OBJ) $(TEXTURE_OBJ) $(XM_OBJ) $(LIBGCC)