add channel "keyon" visualization

This commit is contained in:
Zack Buhman 2025-06-25 23:04:29 -05:00
parent 2066923f10
commit 5020f5030b
3 changed files with 120 additions and 9 deletions

View File

@ -561,13 +561,116 @@ void transfer_middle_line(ta_parameter_writer& writer, float x, float y)
0x202020); 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) void transfer_scene(ta_parameter_writer& writer)
{ {
const int x = 3; const int x = 3;
const int y = 48; const int y = 100;
{ // punch-through { // punch-through
global_polygon_textured(writer); global_polygon_textured(writer,
para_control::list_type::punch_through);
transfer_lines(writer, x, y); transfer_lines(writer, x, y);
@ -593,6 +696,8 @@ void transfer_scene(ta_parameter_writer& writer)
transfer_borders(writer, x, y); transfer_borders(writer, x, y);
transfer_channel_status(writer, 0, 0);
writer.append<ta_global_parameter::end_of_list>() = writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list); ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
} }

View File

@ -113,7 +113,7 @@ 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);
} }
state.channel[ch].keyon = 1; state.channel[ch].keyon = 255;
wait(); aica_sound.channel[ch].KYONB(0); wait(); aica_sound.channel[ch].KYONB(0);
} }
@ -227,9 +227,9 @@ void interrupt()
break; break;
} }
*/ */
if (state.channel[ch].keyon != 0) { if (state.channel[ch].keyon == 255) {
wait(); aica_sound.channel[ch].KYONB(1); wait(); aica_sound.channel[ch].KYONB(1);
state.channel[ch].keyon = 0; state.channel[ch].keyon -= 1;
} }
} }
wait(); aica_sound.channel[0].KYONEX(1); wait(); aica_sound.channel[0].KYONEX(1);
@ -237,6 +237,12 @@ void interrupt()
if ((state.interrupt_clock % state.tick_rate) != 0) { if ((state.interrupt_clock % state.tick_rate) != 0) {
return; return;
} }
for (int ch = 0; ch < 64; ch++) {
int keyon = state.channel[ch].keyon;
if (keyon != 255 && keyon != 0) {
state.channel[ch].keyon -= 1;
}
}
int tick = state.tick % state.ticks_per_line; int tick = state.tick % state.ticks_per_line;
bool note_tick = tick == 0; bool note_tick = tick == 0;

View File

@ -1,12 +1,12 @@
void global_polygon_textured(ta_parameter_writer& writer) 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 const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::punch_through | list_type
| obj_control::col_type::packed_color | obj_control::col_type::packed_color
| obj_control::texture | obj_control::texture
; ;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater_or_equal
| isp_tsp_instruction_word::culling_mode::no_culling; | isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate
@ -39,7 +39,7 @@ void global_polygon_untextured(ta_parameter_writer& writer, uint32_t list_type,
| obj_control::col_type::packed_color | obj_control::col_type::packed_color
; ;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater_or_equal
| isp_tsp_instruction_word::culling_mode::no_culling; | isp_tsp_instruction_word::culling_mode::no_culling;
const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate const uint32_t tsp_instruction_word = tsp_instruction_word::texture_shading_instruction::modulate