From ff6e784e7c5ebe223666c6c631305397ad358289 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 23 Apr 2023 15:48:59 +0200 Subject: Start decoupling of rendering from update passes --- src/drawing.c | 1237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1237 insertions(+) create mode 100644 src/drawing.c (limited to 'src/drawing.c') diff --git a/src/drawing.c b/src/drawing.c new file mode 100644 index 0000000..4f08e39 --- /dev/null +++ b/src/drawing.c @@ -0,0 +1,1237 @@ +// +// Channel render functions. +// + +void +draw_channel_sprite(size_t x, size_t y, u8 clr, u8 idx) { + draw_icn(x, y, &ch_btn_sprite[0 + 6 * idx], clr, 0, 0); + draw_icn(x + 8, y, &ch_btn_sprite[2 + 6 * idx], clr, 0, 0); + draw_icn(x + 16, y, &ch_btn_sprite[4 + 6 * idx], clr, 0, 0); +} + +void +draw_channels(void) { + for (size_t i = 0; i < 4; i++) { + bool active = false; + switch (i) { + case 0: { + active = patterns[pattern_selection_loc].ch1.active; + } break; + case 1: { + active = patterns[pattern_selection_loc].ch2.active; + } break; + case 2: { + active = patterns[pattern_selection_loc].ch3.active; + } break; + case 3: { + active = patterns[pattern_selection_loc].ch4.active; + } break; + } + u8 clr = active ? COL_FG : COL_GREY; + size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; + draw_channel_sprite(CHAN_START_X, y, active, i); + } +} + +void +draw_channel_cursor(size_t i, u8 clr) { + size_t offset_x = 0; + size_t offset_y = CHAN_H + i * CHAN_OFFSET_Y + 1; + size_t x0 = CHAN_START_X + offset_x; + size_t x1 = CHAN_START_X + offset_x + CHAN_W; + size_t y = CHAN_START_Y + offset_y; + draw_line(x0, y, x1, y, clr); +} + +// +// Trigger render functions. +// + +void +clear_trigger(size_t i) { + size_t offset_x = TRIG_OFFSET_X * (i % 8); + size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y; + size_t x0 = TRIG_START_X + offset_x + 1; + size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1; + size_t y0 = TRIG_START_Y + offset_y + 1; + size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 4; + draw_filled_rect(x0, y0, x1, y1, COL_BG); +} + +void +draw_trigger(size_t chan, size_t i) { + TriggerNote trig = {0}; + switch (chan) { + case 0: { + trig = patterns[pattern_selection_loc].ch1.notes[i]; + } break; + case 1: { + trig = patterns[pattern_selection_loc].ch2.notes[i]; + } break; + case 2: { + trig = patterns[pattern_selection_loc].ch3.notes[i]; + } break; + case 3: { + trig = patterns[pattern_selection_loc].ch4.notes[i]; + } break; + } + if (trig.active) { + size_t offset_x = TRIG_OFFSET_X * (i % 8); + size_t offset_y = i < 8 ? 0 : TRIG_OFFSET_Y; + size_t x = TRIG_START_X + offset_x; + size_t y = TRIG_START_Y + offset_y; + u32 *tile = ¬e_name_sprites[4 * trig.note]; + draw_icn(x, y, &tile[0], COL_FG, 1, 0); + draw_icn(x + 8, y, &tile[2], COL_FG, 1, 0); + } else { + clear_trigger(i); + } +} + +void +draw_trig_cursor(size_t i, u8 clr) { + size_t offset_x = TRIG_OFFSET_X * (i % 8); + size_t offset_y = i < 8 ? 2 : 2 + TRIG_OFFSET_Y; + size_t x0 = TRIG_START_X + offset_x; + size_t x1 = TRIG_START_X + TRIG_W + offset_x; + size_t y = TRIG_START_Y + TRIG_H + offset_y; + draw_line(x0, y, x1, y, clr); +} + +void +draw_right_col_cursor(u8 clr) { + size_t x0 = 0; + size_t x1 = 0; + size_t y = 0; + switch (right_col_selection_loc) { + case R_COL_BPM: { + x0 = BPM_START_X; + x1 = x0 + R_COL_W; + y = BPM_START_Y + BPM_H + 2; + } break; + case R_COL_STOP: { + x0 = STOP_START_X; + x1 = x0 + R_COL_W; + y = STOP_START_Y + PLAY_STOP_H + 2; + } break; + case R_COL_PLAY: { + x0 = PLAY_START_X; + x1 = x0 + R_COL_W; + y = PLAY_START_Y + PLAY_STOP_H + 2; + } break; + case R_COL_BANK_A: { + x0 = BANK_START_X; + x1 = x0 + PAT_W; + y = BANK_START_Y + PAT_H + 2; + } break; + case R_COL_BANK_B: { + x0 = BANK_START_X; + x1 = x0 + PAT_W; + y = BANK_START_Y + PAT_H + 2 + 1 * PAT_OFFSET_Y; + } break; + case R_COL_BANK_C: { + x0 = BANK_START_X; + x1 = x0 + PAT_W; + y = BANK_START_Y + PAT_H + 2 + 2 * PAT_OFFSET_Y; + } break; + case R_COL_BANK_D: { + x0 = BANK_START_X; + x1 = x0 + PAT_W; + y = BANK_START_Y + PAT_H + 2 + 3 * PAT_OFFSET_Y; + } break; + } + draw_line(x0, y, x1, y, clr); +} + +void +draw_current_step(u8 col) { + size_t offset_x = TRIG_OFFSET_X * (step_counter % 8); + size_t offset_y = step_counter < 8 ? 2 : 2 + TRIG_OFFSET_Y; + size_t x0 = TRIG_START_X + 3 + offset_x; + size_t x1 = TRIG_START_X - 3 + TRIG_W + offset_x; + size_t y = TRIG_START_Y - 4 + TRIG_H + offset_y; + draw_line(x0, y, x1, y, col); +} + +void +draw_bank_buttons() { + size_t x = BANK_START_X; + size_t y = BANK_START_Y; + // txt_drawf_small("BANK", x - 2, y - 10, 4, COL_FG); + char bank_names[] = { + 'A', 'B', 'C', 'D', + }; + for (int i = 0; i < 4; i++) { + int color = COL_GREY; + if (i == current_bank) { + color = COL_FG; + } + draw_filled_rect(x, y, x + PAT_W, y + PAT_H, COL_BG); + draw_rect(x, y, x + PAT_W, y + PAT_H, color); + // txt_drawc(bank_names[i], x + 4, y + 2, 6, color); + y += PAT_OFFSET_Y; + } +} + +void +draw_pattern_buttons() { + size_t x = PAT_START_X; + size_t y = PAT_START_Y; + // txt_drawf_small("PAT", x, y - 10, 4, COL_FG); + char pat_names[] = { + 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', + }; + for (int i = 0; i < 8; i++) { + int color = COL_GREY; + if (i == current_pattern) { + color = COL_FG; + } + if (i == next_pattern && current_pattern != next_pattern) { + color = COL_BLUE; + } + draw_filled_rect(x, y, x + PAT_W, y + PAT_H, COL_BG); + draw_rect(x, y, x + PAT_W, y + PAT_H, color); + // txt_drawc(pat_names[i], x + 4, y + 2, 6, color); + y += PAT_OFFSET_Y; + } +} + +void +draw_pattern_cursor(size_t i, u8 clr) { + size_t offset_x = 0; + size_t offset_y = PAT_H + i * PAT_OFFSET_Y + 2; + size_t x0 = PAT_START_X + offset_x; + size_t x1 = PAT_START_X + offset_x + PAT_W; + size_t y = PAT_START_Y + offset_y; + draw_line(x0, y, x1, y, clr); +} + +void +draw_play() { + size_t x = PLAY_START_X; + size_t y = PLAY_START_Y; + draw_filled_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_BG); + draw_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_CYAN); + if (play_status == 1) { + // Pause button + draw_filled_rect(x + 10, y + 3, x + 11, y + 7, COL_CYAN); + draw_filled_rect(x + 13, y + 3, x + 14, y + 7, COL_CYAN); + } else { + // Play button + x += 1; + draw_line(x + 10, y + 2, x + 10, y + 8, COL_CYAN); + draw_line(x + 11, y + 3, x + 11, y + 7, COL_CYAN); + draw_line(x + 12, y + 4, x + 12, y + 6, COL_CYAN); + draw_line(x + 13, y + 5, x + 13, y + 5, COL_CYAN); + } +} + +void +draw_stop() { + size_t x = STOP_START_X; + size_t y = STOP_START_Y; + draw_rect(x, y, x + R_COL_W, y + PLAY_STOP_H, COL_RED); + draw_filled_rect(x + 10, y + 3, x + 14, y + 7, COL_RED); +} + +void +draw_bpm() { + size_t x = BPM_START_X; + size_t y = BPM_START_Y; + + // Draw bounding box. + draw_filled_rect(x, y, x + R_COL_W, y + BPM_H, COL_BG); + draw_rect(x, y, x + R_COL_W, y + BPM_H, COL_FG); + draw_line(x + 5, y, x + 19, y, COL_BG); + // txt_drawf_small("BPM", x + 5, y - 4, 4, COL_FG); + + // Make sure its horizontally centered if only 2 digits + int bpm = patterns[pattern_selection_loc].bpm; + if (bpm >= 100) { + txt_drawf("%d", x + 3, y + 7, 6, COL_FG, bpm); + } else { + txt_drawf("%d", x + 6, y + 7, 6, COL_FG, bpm); + } +} + +void +draw_triggers(void) { + for (size_t i = 0; i < 16; i++) { + size_t offset_x = TRIG_OFFSET_X * (i % 8); + size_t offset_y = i < 8 ? 0 : 0 + TRIG_OFFSET_Y; + size_t x0 = TRIG_START_X + offset_x; + size_t x1 = TRIG_START_X + offset_x + TRIG_W; + size_t y0 = TRIG_START_Y + offset_y; + size_t y1 = TRIG_START_Y + offset_y + TRIG_H; + draw_rect(x0, y0, x1, y1, COL_FG); + clear_trigger(i); + draw_trigger(channel_selection_loc, i); + } +} + +void +draw_note(u8 note, u8 clr) { + size_t octave = note / 12; + size_t value = note % 12; + + size_t x0 = 0; + size_t y0 = 0; + size_t x1 = 0; + size_t y1 = 0; + switch (value) { + // White notes. + case 0:{ + x0 = PIANO_START_X + 2 + octave * 28; + x1 = x0 + 1; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + PIANO_H; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 2; + x1 = x0; + y0 = y0 + 9; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 2:{ + x0 = PIANO_START_X + 2 + octave * 28 + 5; + x1 = x0; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 12; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 4; + x1 = x0 + 2; + y0 = PIANO_START_Y - 2 + 13; + y1 = y0 + 7; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 4:{ + x0 = PIANO_START_X + 2 + octave * 28 + 9; + x1 = x0 + 1; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 12; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 8; + x1 = x0 + 2; + y0 = PIANO_START_Y - 2 + 13; + y1 = y0 + 7; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 5:{ + x0 = PIANO_START_X + 2 + octave * 28 + 12; + x1 = x0 + 1; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + PIANO_H; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 14; + x1 = x0; + y0 = y0 + 9; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 7:{ + x0 = PIANO_START_X + 2 + octave * 28 + 17; + x1 = x0; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 12; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 16; + x1 = x0 + 2; + y0 = PIANO_START_Y - 2 + 13; + y1 = y0 + 7; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 9:{ + x0 = PIANO_START_X + 2 + octave * 28 + 21; + x1 = x0; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 12; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 20; + x1 = x0 + 2; + y0 = PIANO_START_Y - 2 + 13; + y1 = y0 + 7; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + case 11: { + x0 = PIANO_START_X + 2 + octave * 28 + 25; + x1 = x0 + 1; + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 12; + draw_filled_rect(x0, y0, x1, y1, clr); + x0 = PIANO_START_X + 2 + octave * 28 + 24; + x1 = x0 + 2; + y0 = PIANO_START_Y - 2 + 13; + y1 = y0 + 7; + draw_filled_rect(x0, y0, x1, y1, clr); + } break; + default: { + if (clr == COL_FG) { + clr = COL_BG; + } + y0 = PIANO_START_Y + 2; + y1 = PIANO_START_Y - 2 + 11; + switch (value) { + case 1: { + x0 = PIANO_START_X + 2 + octave * 28 + 3; + } break; + case 3: { + x0 = PIANO_START_X + 2 + octave * 28 + 7; + } break; + case 6: { + x0 = PIANO_START_X + 2 + octave * 28 + 15; + } break; + case 8: { + x0 = PIANO_START_X + 2 + octave * 28 + 19; + } break; + case 10: { + x0 = PIANO_START_X + 2 + octave * 28 + 23; + } break; + } + x1 = x0; + draw_line(x0, y0, x1, y1, clr); + } break; + } +} + +void +draw_piano(void) { + size_t x0 = PIANO_START_X; + size_t x1 = PIANO_START_X + PIANO_W; + size_t y0 = PIANO_START_Y; + size_t y1 = PIANO_START_Y + PIANO_H; + draw_rect(x0, y0, x1, y1, COL_FG); + for (size_t i = 0; i < 12 * 6; i++) { + draw_note(i, COL_FG); + } +} + +void +draw_params_cursor_wave(size_t i, u8 clr) { + u8 x_positions[] = { + // 32 half bytes (Wave A). + 0, 4, 8, 12, 16, 20, 24, 28, + 34, 38, 42, 46, 50, 54, 58, 62, + 0, 4, 8, 12, 16, 20, 24, 28, + 34, 38, 42, 46, 50, 54, 58, 62, + // 32 half bytes (Wave B). + 70, 74, 78, 82, 86, 90, 94, 98, + 104, 108, 112, 116, 120, 124, 128, 132, + 70, 74, 78, 82, 86, 90, 94, 98, + 104, 108, 112, 116, 120, 124, 128, 132, + // Default wave A. + 1, 18, 35, 52, + // Default wave B. + 71, 88, 105, 122, + // Mode selection. + 141, + // Volume selection. + 141, + }; + u8 y_positions[] = { + // 32 half bytes (Wave A) + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + // 32 half bytes (Wave B) + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + // Default wave A. + 20, 20, 20, 20, + // Default wave B. + 20, 20, 20, 20, + // Mode selection. + 20, + // Volume selection. + 0, + }; + size_t cursor_length = 0; + if (i < 64) { + cursor_length = 4; + } else if (i < 72) { + cursor_length = 13; + } else { + cursor_length = 30; + } + size_t x = PARAMS_START_X + x_positions[i] - 1; + size_t y = PARAMS_START_Y + PARAMS_H - 23 + y_positions[i]; + draw_line(x, y, x + cursor_length, y, clr); +} + +void +draw_params_cursor_noise(size_t i, u8 clr) { + u8 x_positions[] = { + 0, // Bit mode. + 31, // Env. Vol. + 59, // Env. Direction. + 87, // Env. Time. + }; + u8 y_positions[] = { + 20, // Bit mode. + 20, // Env. Vol. + 20, // Env. Direction. + 20, // Env. Time. + }; + size_t cursor_length = 24; + size_t x = PARAMS_START_X + x_positions[i] + 30; + size_t y = PARAMS_START_Y + PARAMS_H - 23 + y_positions[i]; + draw_line(x, y, x + cursor_length, y, clr); +} + +void +draw_params_cursor_square(size_t i, u8 clr, bool sweep) { + size_t x_offset = sweep ? 0 : 30; + u8 x_positions[] = { + 0, // Duty. + 31, // Env. Vol. + 59, // Env. Direction. + 87, // Env. Time. + 118, // Sweep Number. + 146, // Sweep Time. + 132, // Sweep Direction. + }; + u8 y_positions[] = { + 20, // Duty. + 20, // Env. Vol. + 20, // Env. Direction. + 20, // Env. Time. + 20, // Sweep Number. + 20, // Sweep Time. + 0, // Sweep Direction. + }; + size_t cursor_length = 24; + size_t x = PARAMS_START_X + x_positions[i] + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 23 + y_positions[i]; + draw_line(x, y, x + cursor_length, y, clr); +} + +void +draw_params_cursor(size_t i, u8 clr) { + switch (channel_selection_loc) { + case 0: { + draw_params_cursor_square(i, clr, true); + } break; + case 1: { + draw_params_cursor_square(i, clr, false); + } break; + case 2: { + draw_params_cursor_wave(i, clr); + } break; + case 3: { + draw_params_cursor_noise(i, clr); + } break; + } +} + +IWRAM_CODE +void +draw_wave_pattern(u8 *pattern, int x, int y, u8 clr) { + for (size_t i = 0; i < 16; ++i) { + u8 byte = pattern[i]; + u8 first = (byte >> 4) & 0xF; + u8 second = byte & 0xF; + u8 a = x + i * 4; + u8 b = y + 16; + draw_pixel(a, b - first, clr); + draw_pixel(a + 1, b - first, clr); + draw_pixel(a + 2, b - second, clr); + draw_pixel(a + 3, b - second, clr); + } +} + +IWRAM_CODE +void +clear_parameters(void) { + size_t x0 = PARAMS_START_X; + size_t y0 = PARAMS_START_Y; + size_t x1 = PARAMS_START_X + PARAMS_W; + size_t y1 = PARAMS_START_Y + PARAMS_H - 1; + draw_filled_rect(x0, y0, x1, y1, COL_BG); +} + +IWRAM_CODE +void +draw_parameters_wave(void) { + // Draw current wave data. + Pattern *pat = &patterns[pattern_selection_loc]; + { + u8 *wave_a = pat->ch3.params[trig_selection_loc].wave_a; + u8 *wave_b = pat->ch3.params[trig_selection_loc].wave_b; + + size_t x = PARAMS_START_X; + size_t y = PARAMS_START_Y + 13; + + // Wave Patterns. + draw_wave_pattern(wave_a, x, y, COL_WAVE_A); + draw_wave_pattern(wave_b, x + 70, y, COL_WAVE_B); + + // Wave text. + x -= 2; + // txt_drawf_small("%02x%02x%02x%02x", x, y + 20, 4, COL_FG, + // wave_a[0], wave_a[1], wave_a[2], wave_a[3]); + // txt_drawf_small("%02x%02x%02x%02x", x + 34, y + 20, 4, COL_FG, + // wave_a[4], wave_a[5], wave_a[6], wave_a[7]); + // txt_drawf_small("%02x%02x%02x%02x", x, y + 28, 4, COL_FG, + // wave_a[8], wave_a[9], wave_a[10], wave_a[11]); + // txt_drawf_small("%02x%02x%02x%02x", x + 34, y + 28, 4, COL_FG, + // wave_a[12], wave_a[13], wave_a[14], wave_a[15]); + + x += 70; + // txt_drawf_small("%02x%02x%02x%02x", x, y + 20, 4, COL_FG, + // wave_b[0], wave_b[1], wave_b[2], wave_b[3]); + // txt_drawf_small("%02x%02x%02x%02x", x + 34, y + 20, 4, COL_FG, + // wave_b[4], wave_b[5], wave_b[6], wave_b[7]); + // txt_drawf_small("%02x%02x%02x%02x", x, y + 28, 4, COL_FG, + // wave_b[8], wave_b[9], wave_b[10], wave_b[11]); + // txt_drawf_small("%02x%02x%02x%02x", x + 34, y + 28, 4, COL_FG, + // wave_b[12], wave_b[13], wave_b[14], wave_b[15]); + } + + // Draw default wave buttons. + { + // Tile *wave_tiles = ASSETS_DEFAULT_WAVES; + size_t x = PARAMS_START_X; + size_t y = PARAMS_START_Y + PARAMS_H - 12; + for (size_t i = 0, k = 0; i < 4 * 2; i += 2, k++) { + // draw_tile(x + 17 * k, y, wave_tiles + i, COL_FG, true); + // draw_tile(x + 17 * k + 8, y, wave_tiles + i + 1, COL_FG, true); + } + for (size_t i = 0, k = 0; i < 4 * 2; i += 2, k++) { + // draw_tile(x + 17 * k + 70, y, wave_tiles + i, COL_FG, true); + // draw_tile(x + 17 * k + 8 + 70, y, wave_tiles + i + 1, COL_FG, true); + } + } + + // Mode selection. + { + size_t x = PARAMS_START_X + 140; + size_t y = PARAMS_START_Y + PARAMS_H - 22; + draw_line(x, y + 4, x + 5, y + 4, COL_FG); + draw_line(x + 25, y + 4, x + 30, y + 4, COL_FG); + draw_line(x, y + 5, x, y + 16, COL_FG); + draw_line(x + 30, y + 5, x + 30, y + 17, COL_FG); + draw_line(x, y + 17, x + 30, y + 17, COL_FG); + // txt_drawf_small("mode", x + 6, y, 4, COL_FG); + + switch (pat->ch3.params[trig_selection_loc].wave_mode) { + case 0: { + txt_drawf("A", x + 12, y + 7, 6, COL_FG); + } break; + case 1: { + txt_drawf("B", x + 12, y + 7, 6, COL_FG); + } break; + case 2: { + txt_drawf("A+B", x + 6, y + 7, 6, COL_FG); + } break; + } + } + + // Wave volume. + { + size_t x = PARAMS_START_X + 140; + size_t y = PARAMS_START_Y + PARAMS_H - 45; + draw_line(x, y + 7, x + 7, y + 7, COL_FG); + draw_line(x + 23, y + 7, x + 30, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 30, y + 8, x + 30, y + 19, COL_FG); + draw_line(x, y + 20, x + 30, y + 20, COL_FG); + // txt_drawf_small("vol", x + 8, y + 3, 4, COL_FG); + + switch (pat->ch3.params[trig_selection_loc].wave_volume) { + case 0: { + txt_drawf("0", x + 12, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("25", x + 9, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("50", x + 9, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("75", x + 9, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("100", x + 6, y + 10, 6, COL_FG); + } break; + } + } +} + +void +draw_parameters_square(ChannelSquareParams *params, bool sweep) { + size_t x_offset = sweep ? 0 : 30; + + // Duty cycle. + { + // Shape drawing. + { + size_t x = PARAMS_START_X + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 44; + + size_t x0 = x + 2; + size_t x1 = x0; + size_t x2 = x0; + size_t x3 = x0; + size_t x4 = x0; + size_t x5 = x0; + size_t y0 = y + 14; + size_t y1 = y + 2; + + switch (params->duty_cycle) { + case 0: { + x1 += 4; + x2 += 6; + x3 += 13; + x4 += 15; + x5 += 20; + } break; + case 1: { + x1 += 4; + x2 += 7; + x3 += 13; + x4 += 16; + x5 += 20; + } break; + case 2: { + x1 += 3; + x2 += 8; + x3 += 12; + x4 += 17; + x5 += 20; + } break; + case 3: { + x1 += 2; + x2 += 9; + x3 += 11; + x4 += 18; + x5 += 20; + } break; + } + draw_line(x0, y0, x1, y0, COL_RED); + draw_line(x1, y1, x1, y0, COL_RED); + draw_line(x1, y1, x2, y1, COL_RED); + draw_line(x2, y1, x2, y0, COL_RED); + draw_line(x2, y0, x3, y0, COL_RED); + draw_line(x3, y1, x3, y0, COL_RED); + draw_line(x3, y1, x4, y1, COL_RED); + draw_line(x4, y1, x4, y0, COL_RED); + draw_line(x4, y0, x5, y0, COL_RED); + + // Bounding box. + draw_rect(x, y - 3, x + 24, y + 18, COL_RED); + } + + // Param box. + { + size_t x = PARAMS_START_X + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 2, y + 7, COL_FG); + draw_line(x + 22, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("duty", x + 3, y + 3, 4, COL_FG); + + switch (params->duty_cycle) { + case 0: { + txt_drawf("12", x + 6, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("25", x + 6, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("50", x + 6, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("75", x + 6, y + 10, 6, COL_FG); + } break; + } + } + } + + // Envelope. + { + // Env. drawing. + { + // Bounding box. + { + size_t x0 = PARAMS_START_X + 31 + x_offset; + size_t y0 = PARAMS_START_Y + PARAMS_H - 47; + size_t x1 = x0 + 79; + size_t y1 = y0 + 21; + draw_rect(x0, y0, x1, y1, COL_CYAN); + } + + size_t x = PARAMS_START_X + 42 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 44; + size_t x0 = x; + size_t y0 = y + 15 - params->env_volume; + size_t x1 = x + 8 * params->env_time; + size_t y1 = params->env_direction == 0 ? y + 15 : y; + size_t x2 = x + 8 * 7 + 1; + size_t y2 = y1; + + // Env. + if (params->env_time == 0) { + draw_line(x1, y0, x2, y0, COL_CYAN); + } else { + draw_line(x0, y0, x1, y1, COL_CYAN); + draw_line(x1, y1, x2, y2, COL_CYAN); + } + } + + // Env. volume. + { + size_t x = PARAMS_START_X + 31 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("vol", x + 5, y + 3, 4, COL_FG); + + switch (params->env_volume) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("6", x + 9, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("13", x + 6, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("20", x + 6, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("26", x + 6, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("33", x + 6, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("40", x + 6, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("46", x + 6, y + 10, 6, COL_FG); + } break; + case 8: { + txt_drawf("53", x + 6, y + 10, 6, COL_FG); + } break; + case 9: { + txt_drawf("60", x + 6, y + 10, 6, COL_FG); + } break; + case 10: { + txt_drawf("66", x + 6, y + 10, 6, COL_FG); + } break; + case 11: { + txt_drawf("73", x + 6, y + 10, 6, COL_FG); + } break; + case 12: { + txt_drawf("80", x + 6, y + 10, 6, COL_FG); + } break; + case 13: { + txt_drawf("86", x + 6, y + 10, 6, COL_FG); + } break; + case 14: { + txt_drawf("93", x + 6, y + 10, 6, COL_FG); + } break; + case 15: { + txt_drawf("100", x + 3, y + 10, 6, COL_FG); + } break; + } + } + + // Env. direction + { + size_t x = PARAMS_START_X + 59 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("dir", x + 5, y + 3, 4, COL_FG); + + char arr_up[2] = { 0x19, 0 }; + char arr_down[2] = { 0x18, 0 }; + switch (params->env_direction) { + case 0: { + txt_drawf(arr_up, x + 9, y + 11, 6, COL_FG); + } break; + case 1: { + txt_drawf(arr_down, x + 9, y + 11, 6, COL_FG); + } break; + } + } + + // Env. time. + { + size_t x = PARAMS_START_X + 87 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 2, y + 7, COL_FG); + draw_line(x + 22, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("time", x + 3, y + 3, 4, COL_FG); + + switch (params->env_time) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("14", x + 6, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("28", x + 6, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("42", x + 6, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("57", x + 6, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("71", x + 6, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("85", x + 6, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("100", x + 3, y + 10, 6, COL_FG); + } break; + } + } + } + + // Sweep number. + if (sweep) { + size_t x = PARAMS_START_X + 118; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("num", x + 5, y + 3, 4, COL_FG); + + switch (params->sweep_number) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("1", x + 9, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("2", x + 9, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("3", x + 9, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("4", x + 9, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("5", x + 9, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("6", x + 9, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("7", x + 9, y + 10, 6, COL_FG); + } break; + } + } + + // Sweep time. + if (sweep) { + size_t x = PARAMS_START_X + 146; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 2, y + 7, COL_FG); + draw_line(x + 22, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("time", x + 3, y + 3, 4, COL_FG); + + switch (params->sweep_time) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("1", x + 9, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("2", x + 9, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("3", x + 9, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("4", x + 9, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("5", x + 9, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("6", x + 9, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("7", x + 9, y + 10, 6, COL_FG); + } break; + } + } + + // Sweep direction. + if (sweep) { + size_t x = PARAMS_START_X + 132; + size_t y = PARAMS_START_Y + PARAMS_H - 45; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("dir", x + 5, y + 3, 4, COL_FG); + + char arr_up[2] = { 0x19, 0 }; + char arr_down[2] = { 0x18, 0 }; + switch (params->sweep_direction) { + case 0: { + txt_drawf(arr_up, x + 9, y + 11, 6, COL_FG); + } break; + case 1: { + txt_drawf(arr_down, x + 9, y + 11, 6, COL_FG); + } break; + } + } + + // Labels. + { + size_t x = PARAMS_START_X + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 45; + // txt_drawf_small("shape", x + 1, y - 12, 4, COL_FG); + // txt_drawf_small("envelope", x + 54, y - 12, 4, COL_FG); + if (sweep) { + // txt_drawf_small("sweep", x + 133, y - 12, 4, COL_FG); + } + } +} + +void +draw_parameters_noise(void) { + size_t x_offset = 30; + Pattern *pat = &patterns[pattern_selection_loc]; + ChannelNoiseParams *params = &pat->ch4.params[trig_selection_loc]; + + // Bit mode. + { + // Param box. + { + size_t x = PARAMS_START_X + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 2, y + 7, COL_FG); + draw_line(x + 22, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("mode", x + 3, y + 3, 4, COL_FG); + + switch (params->bit_mode) { + case 0: { + txt_drawf("A", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("B", x + 9, y + 10, 6, COL_FG); + } break; + } + } + } + + // Envelope. + { + // Env. drawing. + { + // Bounding box. + { + size_t x0 = PARAMS_START_X + 31 + x_offset; + size_t y0 = PARAMS_START_Y + PARAMS_H - 47; + size_t x1 = x0 + 79; + size_t y1 = y0 + 21; + draw_rect(x0, y0, x1, y1, COL_CYAN); + } + + size_t x = PARAMS_START_X + 42 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 44; + size_t x0 = x; + size_t y0 = y + 15 - params->env_volume; + size_t x1 = x + 8 * params->env_time; + size_t y1 = params->env_direction == 0 ? y + 15 : y; + size_t x2 = x + 8 * 7 + 1; + size_t y2 = y1; + + // Env. + if (params->env_time == 0) { + draw_line(x1, y0, x2, y0, COL_CYAN); + } else { + draw_line(x0, y0, x1, y1, COL_CYAN); + draw_line(x1, y1, x2, y2, COL_CYAN); + } + } + + // Env. volume. + { + size_t x = PARAMS_START_X + 31 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("vol", x + 5, y + 3, 4, COL_FG); + + switch (params->env_volume) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("6", x + 9, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("13", x + 6, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("20", x + 6, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("26", x + 6, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("33", x + 6, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("40", x + 6, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("46", x + 6, y + 10, 6, COL_FG); + } break; + case 8: { + txt_drawf("53", x + 6, y + 10, 6, COL_FG); + } break; + case 9: { + txt_drawf("60", x + 6, y + 10, 6, COL_FG); + } break; + case 10: { + txt_drawf("66", x + 6, y + 10, 6, COL_FG); + } break; + case 11: { + txt_drawf("73", x + 6, y + 10, 6, COL_FG); + } break; + case 12: { + txt_drawf("80", x + 6, y + 10, 6, COL_FG); + } break; + case 13: { + txt_drawf("86", x + 6, y + 10, 6, COL_FG); + } break; + case 14: { + txt_drawf("93", x + 6, y + 10, 6, COL_FG); + } break; + case 15: { + txt_drawf("100", x + 3, y + 10, 6, COL_FG); + } break; + } + } + + // Env. direction + { + size_t x = PARAMS_START_X + 59 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 4, y + 7, COL_FG); + draw_line(x + 20, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("dir", x + 5, y + 3, 4, COL_FG); + + char arr_up[2] = { 0x19, 0 }; + char arr_down[2] = { 0x18, 0 }; + switch (params->env_direction) { + case 0: { + txt_drawf(arr_up, x + 9, y + 11, 6, COL_FG); + } break; + case 1: { + txt_drawf(arr_down, x + 9, y + 11, 6, COL_FG); + } break; + } + } + + // Env. time. + { + size_t x = PARAMS_START_X + 87 + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 25; + draw_line(x, y + 7, x + 2, y + 7, COL_FG); + draw_line(x + 22, y + 7, x + 24, y + 7, COL_FG); + draw_line(x, y + 8, x, y + 19, COL_FG); + draw_line(x + 24, y + 8, x + 24, y + 19, COL_FG); + draw_line(x, y + 20, x + 24, y + 20, COL_FG); + // txt_drawf_small("time", x + 3, y + 3, 4, COL_FG); + + switch (params->env_time) { + case 0: { + txt_drawf("0", x + 9, y + 10, 6, COL_FG); + } break; + case 1: { + txt_drawf("14", x + 6, y + 10, 6, COL_FG); + } break; + case 2: { + txt_drawf("28", x + 6, y + 10, 6, COL_FG); + } break; + case 3: { + txt_drawf("42", x + 6, y + 10, 6, COL_FG); + } break; + case 4: { + txt_drawf("57", x + 6, y + 10, 6, COL_FG); + } break; + case 5: { + txt_drawf("71", x + 6, y + 10, 6, COL_FG); + } break; + case 6: { + txt_drawf("85", x + 6, y + 10, 6, COL_FG); + } break; + case 7: { + txt_drawf("100", x + 3, y + 10, 6, COL_FG); + } break; + } + } + } + + // Labels. + { + size_t x = PARAMS_START_X + x_offset; + size_t y = PARAMS_START_Y + PARAMS_H - 45; + // txt_drawf_small("envelope", x + 54, y - 12, 4, COL_FG); + } +} + +void +draw_parameters(void) { + clear_parameters(); + Pattern *pat = &patterns[pattern_selection_loc]; + switch (channel_selection_loc) { + case 0: { + draw_parameters_square(&pat->ch1.params[trig_selection_loc], true); + } break; + case 1: { + draw_parameters_square(&pat->ch2.params[trig_selection_loc], false); + } break; + case 2: { + draw_parameters_wave(); + } break; + case 3: { + draw_parameters_noise(); + } break; + } +} + -- cgit v1.2.1