353 lines
9.4 KiB
C++

#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 = 14;
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;
//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_height;
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_heading(ta_parameter_writer& writer, float x, float y)
{
transfer_string(writer, "pattern:",
x, y, 1.0 / 10.0,
0xa7a7a7);
transfer_integer(writer, interpreter::state.pattern_index,
x + glyph::hori_advance * 10, y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_string(writer, "( / )",
x + glyph::hori_advance * 15, y, 1.0 / 11.0,
0xa7a7a7);
transfer_integer(writer, interpreter::state.pattern_order_table_index,
x + glyph::hori_advance * 17, y, 1.0 / 10.0,
2, ' ',
0xffffff);
transfer_integer(writer, interpreter::state.xm.song_length,
x + glyph::hori_advance * 22, y, 1.0 / 10.0,
2, ' ',
0xffffff);
}
void draw(ta_multiwriter& multi, float x, float y)
{
transfer_global_polygon_glyph(multi.pt);
draw_heading(multi.pt, x, y);
y += glyph::vert_advance + 3;
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);
}
}