From 2faf84d78bf261b6f02648e66f0c84efc1eefd05 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 8 Jun 2021 14:34:13 +0200 Subject: Change draw_tile to allow coloring of flat tiles --- src/renderer.c | 20 +++--- src/renderer.h | 6 +- src/sequencer.c | 214 ++++++++++++++++++++++++++++---------------------------- src/text/text.h | 8 +-- 4 files changed, 126 insertions(+), 122 deletions(-) diff --git a/src/renderer.c b/src/renderer.c index afc9904..0ce3107 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -276,7 +276,7 @@ draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) { IWRAM_CODE void -draw_tile(size_t x, size_t y, Tile *tile, bool merge) { +draw_tile(size_t x, size_t y, Tile *tile, u8 clr, bool merge) { BOUNDCHECK_SCREEN(x, y); // Find row position for the given x/y coordinates. @@ -305,40 +305,40 @@ draw_tile(size_t x, size_t y, Tile *tile, bool merge) { if (start_col == 0 && start_row == 0) { for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i]; + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i] * clr; } dirty_tiles[tile_y] |= 1 << tile_x; } else if (start_row == 0) { for (size_t i = 0; i < 8; i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] << shift_left); - backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] >> shift_right); + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] * clr << shift_left); + backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] * clr >> shift_right); } dirty_tiles[tile_y] |= 1 << tile_x; dirty_tiles[tile_y] |= 1 << (tile_x + 1); } else if (start_col == 0) { for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i]; + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i] * clr; } backbuffer += 8 * 31; for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i]; + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | row[i] * clr; } dirty_tiles[tile_y] |= 1 << tile_x; dirty_tiles[tile_y + 1] |= 1 << tile_x; } else { for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] << shift_left); - backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] >> shift_right); + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] * clr << shift_left); + backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] * clr >> shift_right); } backbuffer += 8 * 31; for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) { BOUNDCHECK_SCREEN(x, y + i); - backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] << shift_left); - backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] >> shift_right); + backbuffer[0] = (backbuffer[0] & ~row_mask_left) | (row[i] * clr << shift_left); + backbuffer[8] = (backbuffer[8] & ~row_mask_right) | (row[i] * clr >> shift_right); } dirty_tiles[tile_y] |= 1 << tile_x; dirty_tiles[tile_y] |= 1 << (tile_x + 1); diff --git a/src/renderer.h b/src/renderer.h index a240b17..4620c27 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -43,8 +43,10 @@ void draw_filled_rect(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr); // Draw a 8x8 tile starting at the (x, y) position. If the merge parameter is // set, colors will be added together instead of replaced. This could lead to -// some merging issues if we are not careful with the chosen colors. -void draw_tile(size_t x, size_t y, Tile *tile, bool merge); +// some merging issues if we are not careful with the chosen colors. The tile +// color will be multiplied by the given clr parameter, which is useful to +// change the color of flat tiles. +void draw_tile(size_t x, size_t y, Tile *tile, u8 clr, bool merge); // Fills the framebuffer with color 0. void clear_screen(void); diff --git a/src/sequencer.c b/src/sequencer.c index 46e57ef..dc3249c 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -1,6 +1,16 @@ #include "rng.c" #include "text.h" +// +// Color indexes. +// +#define COL_BG 0 +#define COL_FG 1 +#define COL_RED 2 +#define COL_BLUE 3 +#define COL_CYAN 4 +#define COL_GREY 5 + // // Assets. // @@ -97,17 +107,11 @@ static const u32 channel_buttons[] = { // // Globals. // -typedef enum { - SEQ_SELECT_TRIGGER, - SEQ_SELECT_CHANNEL, - SEQ_SELECT_PARAMETER, -} SeqSelect; static int bpm = 115; static int step_counter = 0; int trig_selection_loc = 0; int param_selection_loc = 64; int channel_selection_loc = 0; -SeqSelect current_selection = SEQ_SELECT_TRIGGER; // // Wave data. @@ -228,7 +232,7 @@ clear_trigger(size_t i) { 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 - 1; - draw_filled_rect(x0, y0, x1, y1, 0); + draw_filled_rect(x0, y0, x1, y1, COL_BG); } void @@ -240,8 +244,8 @@ draw_trigger(size_t chan, size_t i) { size_t y = TRIG_START_Y + offset_y; Tile *tiles = ASSETS_DATA; tiles += 2 * sequences[chan][i].note; - draw_tile(x, y, tiles, true); - draw_tile(x + 8, y, tiles + 1, true); + draw_tile(x, y, tiles, COL_FG, true); + draw_tile(x + 8, y, tiles + 1, COL_FG, true); } else { clear_trigger(i); } @@ -266,11 +270,14 @@ draw_triggers(void) { 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, 1); + draw_rect(x0, y0, x1, y1, COL_FG); + clear_trigger(i); draw_trigger(channel_selection_loc, i); } } +#define CHAN_W 19 +#define CHAN_H 8 #define CHAN_START_X 35 #define CHAN_START_Y 90 #define CHAN_OFFSET_Y 12 @@ -284,12 +291,22 @@ draw_channels(void) { size_t k = 0; for (size_t i = 0; i < 4; i++) { size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; - draw_tile(CHAN_START_X, y, channel_tiles + k++, false); - draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, false); - draw_tile(CHAN_START_X + 16, y, channel_tiles + k++, false); + draw_tile(CHAN_START_X, y, channel_tiles + k++, COL_FG, false); + draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, COL_FG, false); + draw_tile(CHAN_START_X + 16, y, channel_tiles + k++, COL_FG, false); } } +void +draw_channel_cursor(size_t i, u8 clr) { + size_t offset_x = 0; + size_t offset_y = CHAN_H + i * CHAN_OFFSET_Y; + 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); +} + void irq_timer_0(void) { Note active_note; @@ -392,79 +409,102 @@ set_time(int bpm) { TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; } + +void (*input_handler)(void); + #define SEQ_N_CHANNELS 3 +void handle_trigger_cursor(void); +void handle_channel_cursor(void); + void -trigger_cursor(void) { - SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; - if (key_tap(KEY_LEFT)) { - if (trig_selection_loc == 0 || trig_selection_loc == 8) { - // current_selection = SEQ_SELECT_CHANNEL; +handle_channel_cursor(void) { + if (key_tap(KEY_RIGHT)) { + trig_selection_loc = 0; + param_selection_loc = 0; + input_handler = handle_trigger_cursor; + draw_channel_cursor(channel_selection_loc, COL_GREY); + draw_trig_cursor(trig_selection_loc, COL_BLUE); + } + if (key_tap(KEY_UP)) { + draw_channel_cursor(channel_selection_loc, COL_BG); + if (channel_selection_loc == 0) { + channel_selection_loc = SEQ_N_CHANNELS - 1; } else { - draw_trig_cursor(trig_selection_loc, 0); - trig_selection_loc = MAX(trig_selection_loc - 1, 0); - draw_trig_cursor(trig_selection_loc, 3); + channel_selection_loc = MAX(channel_selection_loc - 1, 0); } - } else if (key_tap(KEY_RIGHT)) { - if (trig_selection_loc != 7) { - draw_trig_cursor(trig_selection_loc, 0); - trig_selection_loc = MIN(trig_selection_loc + 1, 15); - draw_trig_cursor(trig_selection_loc, 3); + draw_channel_cursor(channel_selection_loc, COL_BLUE); + draw_triggers(); + } + if (key_tap(KEY_DOWN)) { + draw_channel_cursor(channel_selection_loc, COL_BG); + if (channel_selection_loc == SEQ_N_CHANNELS - 1) { + channel_selection_loc = 0; + } else { + channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS); } - } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { - draw_trig_cursor(trig_selection_loc, 0); - trig_selection_loc = (trig_selection_loc + 8) % 16; - draw_trig_cursor(trig_selection_loc, 3); - } else if (key_tap(KEY_B)) { + draw_channel_cursor(channel_selection_loc, COL_BLUE); + draw_triggers(); + } +} + +void +handle_trigger_cursor(void) { + SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; + + if (key_tap(KEY_B)) { + // Toggle trigger. trig->trigger ^= 1; + draw_trigger(channel_selection_loc, trig_selection_loc); + } else if (key_tap(KEY_A)) { + // Switch to parameter selection. + // current_selection = SEQ_SELECT_PARAMETER; } else if (key_tap(KEY_L)) { + // Decrease note. if (trig->trigger) { trig->note = MAX(trig->note - 1, NOTE_C_2); + clear_trigger(trig_selection_loc); + draw_trigger(channel_selection_loc, trig_selection_loc); } } else if (key_tap(KEY_R)) { + // Increase note. if (trig->trigger) { trig->note = MIN( trig->note + 1, NOTE_C_8); + clear_trigger(trig_selection_loc); + draw_trigger(channel_selection_loc, trig_selection_loc); } - } else if (key_tap(KEY_A)) { - // Switch to parameter selection. - // current_selection = SEQ_SELECT_PARAMETER; } -} -void (*input_handler)(void); + // Move trigger cursor. + if (key_tap(KEY_LEFT)) { + if (trig_selection_loc == 0 || trig_selection_loc == 8) { + // We are at the boundary, switch to channel selection. + draw_trig_cursor(trig_selection_loc, COL_BG); + input_handler = handle_channel_cursor; + draw_channel_cursor(channel_selection_loc, COL_BLUE); + } else { + draw_trig_cursor(trig_selection_loc, COL_BG); + trig_selection_loc = MAX(trig_selection_loc - 1, 0); + draw_trig_cursor(trig_selection_loc, COL_BLUE); + } + } else if (key_tap(KEY_RIGHT)) { + if (trig_selection_loc != 7) { + draw_trig_cursor(trig_selection_loc, COL_BG); + trig_selection_loc = MIN(trig_selection_loc + 1, 15); + draw_trig_cursor(trig_selection_loc, COL_BLUE); + } + } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { + draw_trig_cursor(trig_selection_loc, COL_BG); + trig_selection_loc = (trig_selection_loc + 8) % 16; + draw_trig_cursor(trig_selection_loc, COL_BLUE); + } +} void handle_sequencer_input(void) { poll_keys(); input_handler(); // SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; - // if (current_selection == SEQ_SELECT_TRIGGER) { - // if (key_tap(KEY_LEFT)) { - // if (trig_selection_loc == 0 || trig_selection_loc == 8) { - // current_selection = SEQ_SELECT_CHANNEL; - // } else { - // trig_selection_loc = MAX(trig_selection_loc - 1, 0); - // } - // } else if (key_tap(KEY_RIGHT)) { - // if (trig_selection_loc != 7) { - // trig_selection_loc = MIN(trig_selection_loc + 1, 15); - // } - // } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { - // trig_selection_loc = (trig_selection_loc + 8) % 16; - // } else if (key_tap(KEY_B)) { - // trig->trigger ^= 1; - // } else if (key_tap(KEY_L)) { - // if (trig->trigger) { - // trig->note = MAX(trig->note - 1, NOTE_C_2); - // } - // } else if (key_tap(KEY_R)) { - // if (trig->trigger) { - // trig->note = MIN( trig->note + 1, NOTE_C_8); - // } - // } else if (key_tap(KEY_A)) { - // // Switch to parameter selection. - // current_selection = SEQ_SELECT_PARAMETER; - // } // } else if (current_selection == SEQ_SELECT_PARAMETER) { // if (channel_selection_loc < 2) { // // Move through the selected synth parameters. @@ -648,38 +688,8 @@ handle_sequencer_input(void) { // } // } - // // Go back to trigger selection. - // if (key_tap(KEY_A)) { - // current_selection = SEQ_SELECT_TRIGGER; - // } - - // // Enable disable trigger. - // if (key_tap(KEY_B)) { - // trig->trigger ^= 1; - // } - // } else if (current_selection == SEQ_SELECT_CHANNEL) { - // if (key_tap(KEY_RIGHT)) { - // current_selection = SEQ_SELECT_TRIGGER; - // trig_selection_loc = 0; - // param_selection_loc = 0; - // } - // if (key_tap(KEY_UP)) { - // if (channel_selection_loc == 0) { - // channel_selection_loc = SEQ_N_CHANNELS - 1; - // } else { - // channel_selection_loc = MAX(channel_selection_loc - 1, 0); - // } - // } - // if (key_tap(KEY_DOWN)) { - // if (channel_selection_loc == SEQ_N_CHANNELS - 1) { - // channel_selection_loc = 0; - // } else { - // channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS); - // } - // } - // } - if (key_tap(KEY_START)) { + // Stop the sequencer or start playing from the beginning. step_counter = 0; if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { set_time(bpm); @@ -689,22 +699,13 @@ handle_sequencer_input(void) { SOUND_SQUARE2_CTRL = 0; SOUND_WAVE_CTRL = 0; } - } - if (key_tap(KEY_SELECT)) { + } else if (key_tap(KEY_SELECT)) { + // Play/pause. TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; SOUND_SQUARE1_CTRL = 0; SOUND_SQUARE2_CTRL = 0; SOUND_WAVE_CTRL = 0; } - - // if (key_tap(KEY_LEFT) - // || key_tap(KEY_RIGHT) - // || key_tap(KEY_UP) - // || key_tap(KEY_DOWN) - // || key_tap(KEY_L) - // || key_tap(KEY_R) - // ) { - // } } void @@ -722,8 +723,9 @@ sequencer_init(void) { draw_channels(); // Initialize input handler. - input_handler = trigger_cursor; + input_handler = handle_trigger_cursor; draw_trig_cursor(trig_selection_loc, 3); + draw_channel_cursor(channel_selection_loc, 5); // Initialize sound system. SOUND_STATUS = SOUND_ENABLE; diff --git a/src/text/text.h b/src/text/text.h index 01dddb0..931227c 100644 --- a/src/text/text.h +++ b/src/text/text.h @@ -109,12 +109,12 @@ txt_position(size_t tile_x, size_t tile_y) { // color merging issues. static inline void -txt_draws(char *msg, size_t x, size_t y, size_t spacing) { +txt_draws(char *msg, size_t x, size_t y, size_t spacing, u8 clr) { while (*msg) { char c = *msg++; Tile *tile = FONT_DATA; tile += c; - draw_tile(x, y, tile, true); + draw_tile(x, y, tile, clr, true); x += spacing; } } @@ -129,11 +129,11 @@ txt_draws(char *msg, size_t x, size_t y, size_t spacing) { // Draws text to the screen with formatting starting on the x and y position and // with custom character spacing. -#define txt_drawf(msg, x, y, s, ...) \ +#define txt_drawf(msg, x, y, s, c, ...) \ { \ char buf[256] = {0}; \ posprintf(buf, msg, ##__VA_ARGS__); \ - txt_draws(buf, x, y, s); \ + txt_draws(buf, x, y, s, c); \ } #endif // TEXT_H -- cgit v1.2.1