#include "../../ta_parameter.hpp" #include "../../graphics_primitive.hpp" #include "../../interpreter.hpp" #include "notes.hpp" #include "framebuffer.hpp" union columns { struct { int note; int instrument; int volume_column_byte; int effect_type; int effect_parameter; }; int col[5]; int count() const { int acc = 0; for (int i = 0; i < 5; i++) { acc += col[i] != 0; } return acc; } int sum() const { int acc = 0; for (int i = 0; i < 5; i++) { acc += col[i]; } return acc; } }; const columns line_columns = { .note = 3, .instrument = 2, .volume_column_byte = 0, // 2 .effect_type = 0, // 1 .effect_parameter = 0, // 1 }; const int line_column_total_advance = line_columns.sum() * glyph::hori_advance; const int line_column_width = line_column_total_advance + (line_columns.count() + 1) + 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; const float depth = 0.0001f; static inline int draw_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, depth, 2, ' ', base_color); x += glyph::hori_advance * len; return x; } static inline int draw_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, depth, base_color); x += glyph::hori_advance; } return x; } static inline int draw_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, depth, base_color); x += glyph::hori_advance; transfer_glyph(writer, glyph::horizontal_bar, x, y, depth, base_color); x += glyph::hori_advance; transfer_glyph(writer, glyph::horizontal_bar, x, y, depth, 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, depth, base_color); x += glyph::hori_advance; transfer_glyph(writer, note_name[1], x, y, depth, base_color); x += glyph::hori_advance; transfer_glyph(writer, '0' + octave, x, y, depth, base_color); x += glyph::hori_advance; } else { x = draw_fill(writer, 3, x, y, base_color); } return x; } static inline int draw_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, depth, 2, glyph::interpunct, base_color); x += glyph::hori_advance * len; } else { x = draw_fill(writer, 2, x, y, base_color); } return x; } static inline int draw_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, depth, 2, glyph::interpunct, base_color); x += glyph::hori_advance * len; } else { x = draw_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 draw_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, depth, base_color); x += glyph::hori_advance; } else { x = draw_fill(writer, 1, x, y, base_color); } return x; } static inline int draw_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, depth, 2, glyph::interpunct, base_color); x += glyph::hori_advance * len; } else { x = draw_fill(writer, 2, x, y, base_color); } return x; } static void draw_line(ta_parameter_writer& writer, int line_index, int x, int y) { using namespace interpreter; x += 3; x += 1; x = draw_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; if (line_columns.note != 0) { x = draw_note(writer, pf.note, x, y); x += 1; } if (line_columns.instrument != 0) { x = draw_instrument(writer, pf.instrument, x, y); x += 1; } if (line_columns.volume_column_byte != 0) { x = draw_volume_column_byte(writer, pf.volume_column_byte, x, y); x += 1; } if (line_columns.effect_type != 0) { x = draw_effect_type(writer, pf.effect_type, x, y); x += 1; } if (line_columns.effect_parameter != 0) { x = draw_effect_parameter(writer, pf.effect_parameter, x, y); x += 1; } x += 3; } } namespace scene::tracker::notes { void draw_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, 0, y, framebuffer.px_width); transfer_horizontal_border(writer, 0, y + line_column_height, framebuffer.px_width); } void draw_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) draw_line(writer, line_ix, x, y); y += glyph::vert_advance; } } void draw_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, depth / 2.0}, {x + 0, y + 1, depth / 2.0}, {x + middle_width, y + 1, depth / 2.0}, {x + middle_width, y + 0, depth / 2.0}, 0x555555); y += 1; quad_type_0(writer, {x + 0, y + 0, depth / 2.0}, {x + 0, y + middle_height, depth / 2.0}, {x + middle_width, y + middle_height, depth / 2.0}, {x + middle_width, y + 0, depth / 2.0}, 0x404040); y += middle_width; quad_type_0(writer, {x + 0, y + 0, depth / 2.0}, {x + 0, y + 1, depth / 2.0}, {x + middle_width, y + 1, depth / 2.0}, {x + middle_width, y + 0, depth / 2.0}, 0x202020); } void draw(ta_multiwriter& multi, float x, float y) { transfer_global_polygon_glyph(multi.pt); draw_lines(multi.pt, x, y); global_polygon_untextured(multi.op, para_control::list_type::opaque, tsp_instruction_word::dst_alpha_instr::zero); draw_borders(multi.op, x, y); draw_middle_line(multi.op, x, y); } }