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/sequencer.c | 2081 +------------------------------------------------------ 1 file changed, 7 insertions(+), 2074 deletions(-) (limited to 'src/sequencer.c') diff --git a/src/sequencer.c b/src/sequencer.c index ff3904d..fd47d0b 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -1,1740 +1,13 @@ +#include "globals.c" #include "rng.c" #include "text.h" +#include "assets.c" +#include "patterns.c" +#include "save.c" +#include "drawing.c" +#include "clipboard.c" -void -sram_read(u8 *dst, u16 pos, u16 n_bytes) { - for (size_t i = 0; i < n_bytes; ++i) { - dst[i] = SRAM[pos + i]; - } -} - -void -sram_write(u8 *src, u16 pos, u16 n_bytes) { - for (size_t i = 0; i < n_bytes; ++i) { - SRAM[pos + i] = src[i]; - } -} - -void set_time(int bpm); -void clipboard_paste(void); -void clipboard_copy(void); - -// -// 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 - -// Theme colors. -#define COL_CURSOR COL_BLUE -#define COL_NOTE_PRESSED COL_GREY -#define COL_WAVE_A COL_RED -#define COL_WAVE_B COL_CYAN - -#define CHAN_W 19 -#define CHAN_H 8 -#define CHAN_START_X 29 -#define CHAN_START_Y 92 -#define CHAN_OFFSET_Y 12 - -#define TRIG_W 15 -#define TRIG_H 24 -#define TRIG_START_X 58 -#define TRIG_START_Y 92 -#define TRIG_OFFSET_X (TRIG_W + 3) -#define TRIG_OFFSET_Y (TRIG_H + 7) - -#define PIANO_W 170 -#define PIANO_H 20 -#define PIANO_START_X 29 -#define PIANO_START_Y 65 -#define PIANO_NOTE_W 2 - -#define PARAMS_W 170 -#define PARAMS_H 64 -#define PARAMS_START_X 29 -#define PARAMS_START_Y 1 - -#define R_SIDEBAR_X ((TRIG_START_X) + (TRIG_OFFSET_X) * 8 + 4) -#define L_SIDEBAR_X ((CHAN_START_X) - 26) - -#define PAT_START_X (L_SIDEBAR_X + 5) -#define PAT_START_Y 18 -#define PAT_W 14 -#define PAT_H 12 -#define PAT_OFFSET_Y 17 - -#define R_COL_W 24 -#define BPM_START_X (R_SIDEBAR_X) -#define BPM_START_Y (TRIG_START_Y + TRIG_H + 9) -#define BPM_H 22 - -#define PLAY_START_X (R_SIDEBAR_X) -#define PLAY_START_Y (TRIG_START_Y) -#define STOP_START_X (R_SIDEBAR_X) -#define STOP_START_Y (TRIG_START_Y + 14) -#define PLAY_STOP_H (10) - -#define BANK_START_X (R_SIDEBAR_X + 5) -#define BANK_START_Y (PAT_START_Y) - -#define SEQ_N_CHANNELS 4 - -// -// Assets. -// - -#define N_TILES_NOTE_NAMES 73 * 2 -#define N_TILES_CHAN_BTSN 4 * 3 -#define N_TILES_WAVE_BTNS 4 * 2 - -#define ASSETS_NOTE_NAMES ((u32*)(MEM_VRAM + KB(32))) -#define ASSETS_CHANNEL_BUTTONS (ASSETS_NOTE_NAMES + (N_TILES_NOTE_NAMES * 8)) -#define ASSETS_DEFAULT_WAVES (ASSETS_CHANNEL_BUTTONS + (N_TILES_CHAN_BTSN * 8)) - -static const u32 note_names[] = { - 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e, - 0x00000098, 0xa8a8a898, 0x00000038, 0x203b0a39, - 0x00000060, 0xa0a0a060, 0x0000000e, 0x080e020e, - 0x000000b8, 0x889888b8, 0x00000038, 0x203b0a39, - 0x000000e0, 0x206020e0, 0x0000000e, 0x080e020e, - 0x000000e0, 0x20602020, 0x0000000e, 0x080e020e, - 0x000000b8, 0x8888a8b8, 0x00000038, 0x203b0a39, - 0x000000e0, 0x2020a0e0, 0x0000000e, 0x080e020e, - 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x203b0a39, - 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x080e020e, - 0x000000b8, 0xa898a8b8, 0x00000038, 0x203b0a39, - 0x000000e0, 0xa060a0e0, 0x0000000e, 0x080e020e, - 0x000000e0, 0x202020e0, 0x0000000e, 0x080c080e, - 0x00000098, 0xa8a8a898, 0x00000038, 0x20332239, - 0x00000060, 0xa0a0a060, 0x0000000e, 0x080c080e, - 0x000000b8, 0x889888b8, 0x00000038, 0x20332239, - 0x000000e0, 0x206020e0, 0x0000000e, 0x080c080e, - 0x000000e0, 0x20602020, 0x0000000e, 0x080c080e, - 0x000000b8, 0x8888a8b8, 0x00000038, 0x20332239, - 0x000000e0, 0x2020a0e0, 0x0000000e, 0x080c080e, - 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x20332239, - 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x080c080e, - 0x000000b8, 0xa898a8b8, 0x00000038, 0x20332239, - 0x000000e0, 0xa060a0e0, 0x0000000e, 0x080c080e, - 0x000000e0, 0x202020e0, 0x0000000a, 0x0a0e0808, - 0x00000098, 0xa8a8a898, 0x00000028, 0x283b2221, - 0x00000060, 0xa0a0a060, 0x0000000a, 0x0a0e0808, - 0x000000b8, 0x889888b8, 0x00000028, 0x283b2221, - 0x000000e0, 0x206020e0, 0x0000000a, 0x0a0e0808, - 0x000000e0, 0x20602020, 0x0000000a, 0x0a0e0808, - 0x000000b8, 0x8888a8b8, 0x00000028, 0x283b2221, - 0x000000e0, 0x2020a0e0, 0x0000000a, 0x0a0e0808, - 0x000000b8, 0xa8a8b8a8, 0x00000028, 0x283b2221, - 0x000000e0, 0xa0a0e0a0, 0x0000000a, 0x0a0e0808, - 0x000000b8, 0xa898a8b8, 0x00000028, 0x283b2221, - 0x000000e0, 0xa060a0e0, 0x0000000a, 0x0a0e0808, - 0x000000e0, 0x202020e0, 0x0000000e, 0x020e080e, - 0x00000098, 0xa8a8a898, 0x00000038, 0x083b2239, - 0x00000060, 0xa0a0a060, 0x0000000e, 0x020e080e, - 0x000000b8, 0x889888b8, 0x00000038, 0x083b2239, - 0x000000e0, 0x206020e0, 0x0000000e, 0x020e080e, - 0x000000e0, 0x20602020, 0x0000000e, 0x020e080e, - 0x000000b8, 0x8888a8b8, 0x00000038, 0x083b2239, - 0x000000e0, 0x2020a0e0, 0x0000000e, 0x020e080e, - 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x083b2239, - 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x020e080e, - 0x000000b8, 0xa898a8b8, 0x00000038, 0x083b2239, - 0x000000e0, 0xa060a0e0, 0x0000000e, 0x020e080e, - 0x000000e0, 0x202020e0, 0x0000000e, 0x020e0a0e, - 0x00000098, 0xa8a8a898, 0x00000038, 0x083b2a39, - 0x00000060, 0xa0a0a060, 0x0000000e, 0x020e0a0e, - 0x000000b8, 0x889888b8, 0x00000038, 0x083b2a39, - 0x000000e0, 0x206020e0, 0x0000000e, 0x020e0a0e, - 0x000000e0, 0x20602020, 0x0000000e, 0x020e0a0e, - 0x000000b8, 0x8888a8b8, 0x00000038, 0x083b2a39, - 0x000000e0, 0x2020a0e0, 0x0000000e, 0x020e0a0e, - 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x083b2a39, - 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x020e0a0e, - 0x000000b8, 0xa898a8b8, 0x00000038, 0x083b2a39, - 0x000000e0, 0xa060a0e0, 0x0000000e, 0x020e0a0e, - 0x000000e0, 0x202020e0, 0x0000000e, 0x08040202, - 0x00000098, 0xa8a8a898, 0x00000038, 0x20130a09, - 0x00000060, 0xa0a0a060, 0x0000000e, 0x08040202, - 0x000000b8, 0x889888b8, 0x00000038, 0x20130a09, - 0x000000e0, 0x206020e0, 0x0000000e, 0x08040202, - 0x000000e0, 0x20602020, 0x0000000e, 0x08040202, - 0x000000b8, 0x8888a8b8, 0x00000038, 0x20130a09, - 0x000000e0, 0x2020a0e0, 0x0000000e, 0x08040202, - 0x000000b8, 0xa8a8b8a8, 0x00000038, 0x20130a09, - 0x000000e0, 0xa0a0e0a0, 0x0000000e, 0x08040202, - 0x000000b8, 0xa898a8b8, 0x00000038, 0x20130a09, - 0x000000e0, 0xa060a0e0, 0x0000000e, 0x08040202, - 0x000000e0, 0x202020e0, 0x0000000e, 0x0a0e0a0e, -}; - -static const u32 channel_buttons[] = { - 0xff017111, 0x117101ff, 0xff008585, 0x879500ff, - 0x0f080808, 0x0808080f, 0xff01b989, 0x89b901ff, - 0xff004242, 0x434a00ff, 0x0f080909, 0x0909080f, - 0xff015d45, 0xc55d01ff, 0xff00a1a1, 0xa1a500ff, - 0x0f080a0a, 0x0a0a080f, 0xff015d45, 0xc55d01ff, - 0xff00a1a1, 0xa12500ff, 0x0f080a0a, 0x0a0b080f, - 0xff01c141, 0xc14101ff, 0xff00151c, 0x141400ff, - 0x0f080808, 0x0808080f, -}; - -static const u32 default_wave_buttons[] = { - 0xff013149, 0x850101ff, 0x3f202028, 0x2423203f, - 0xff016151, 0x49c501ff, 0x3f202c2a, 0x2928203f, - 0xff017d45, 0x45c501ff, 0x3f202828, 0x282f203f, - 0xff014911, 0x812501ff, 0x3f202128, 0x2420203f, -}; - -// -// Wave data. -// - -static const u32 sine_wave[16] = { - 0xefdebc89, 0x98cbedfe, 0x10214376, 0x67341201, -}; - -static const u32 saw_wave[16] = { - 0x67452301, 0xefcdab89, 0x67452301, 0xefcdab89, -}; - -static const u32 square_wave[16] = { - 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, -}; - -// -// Globals. -// - -const int default_bpm = 75; -static int step_counter = 0; -int trig_selection_loc = 0; -int param_selection_loc = 0; -int channel_selection_loc = 0; -int pattern_selection_loc = 0; -int right_col_selection_loc = 0; -int play_status = 0; -static int current_pattern = 0; -static int next_pattern = 0; -static int current_bank = 0; - -enum RIGHT_COL_LOC { - R_COL_BPM = 0, - R_COL_STOP = 1, - R_COL_PLAY = 2, - R_COL_BANK_D = 3, - R_COL_BANK_C = 4, - R_COL_BANK_B = 5, - R_COL_BANK_A = 6, -}; - -typedef struct TriggerNote { - bool active; - Note note; -} TriggerNote; - -typedef struct ChannelSquareParams { - u8 env_volume; - u8 env_time; - u8 env_direction; - u8 duty_cycle; - u8 sweep_number; - u8 sweep_time; - u8 sweep_direction; -} ChannelSquareParams; - -typedef struct ChannelWaveParams { - u8 wave_volume; - u8 wave_mode; - u32 wave_a[4]; - u32 wave_b[4]; -} ChannelWaveParams; - -typedef struct ChannelNoiseParams { - u8 env_volume; - u8 env_time; - u8 env_direction; - u8 bit_mode; -} ChannelNoiseParams; - -typedef struct ChannelSquare { - bool active; - TriggerNote notes[16]; - ChannelSquareParams params[16]; -} ChannelSquare; - -typedef struct ChannelWave { - bool active; - TriggerNote notes[16]; - ChannelWaveParams params[16]; -} ChannelWave; - -typedef struct ChannelNoise { - bool active; - TriggerNote notes[16]; - ChannelNoiseParams params[16]; -} ChannelNoise; - -const ChannelSquare default_ch1 = { - .notes = { - {true, NOTE_C_4}, - {true, NOTE_D_SHARP_4}, - {true, NOTE_G_4}, - {true, NOTE_A_SHARP_4}, - {true, NOTE_C_4}, - {true, NOTE_D_SHARP_4}, - {true, NOTE_G_4}, - {true, NOTE_A_SHARP_4}, - {true, NOTE_C_4}, - {true, NOTE_D_SHARP_4}, - {true, NOTE_G_4}, - {true, NOTE_A_SHARP_4}, - {true, NOTE_C_4}, - {true, NOTE_D_SHARP_4}, - {true, NOTE_G_4}, - {true, NOTE_A_SHARP_4}, - }, - .params = { - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - }, - .active = true, -}; - -const ChannelSquare default_ch2 = { - .notes = { - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - {true, NOTE_C_3}, - }, - .params = { - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - {8, 4, 0, 2, 0, 0, 0}, - }, - .active = true, -}; - -const ChannelWave default_ch3 = { - .notes = { - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_A_SHARP_5}, - {true, NOTE_A_SHARP_5}, - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_G_5}, - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_A_SHARP_5}, - {true, NOTE_A_SHARP_5}, - {true, NOTE_C_5}, - {true, NOTE_C_5}, - {true, NOTE_G_5}, - }, - .params = { - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, - }, - .active = true, -}; - -const ChannelNoise default_ch4 = { - .notes = { - {true, NOTE_D_SHARP_4}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {true, NOTE_D_SHARP_4}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {true, NOTE_D_SHARP_4}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {true, NOTE_D_SHARP_4}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - {false, NOTE_E_6}, - }, - .params = { - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - {0xF, 0x2, 0, 0}, - }, - .active = true, -}; - -typedef struct Metadata { - u8 blank; - u32 magic; - int current_bank; - int current_pattern; -} Metadata; - -static Metadata metadata = {0}; - -typedef struct Pattern { - ChannelSquare ch1; - ChannelSquare ch2; - ChannelWave ch3; - ChannelNoise ch4; - int bpm; - u8 bank; -} Pattern; - -static Pattern patterns[8] = { - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, - {default_ch1, default_ch2, default_ch3, default_ch4, default_bpm, 0}, -}; - -typedef enum ClipboardType { - CLIP_EMPTY, - CLIP_TRIG, - CLIP_PARAM_CH1, - CLIP_PARAM_CH2, - CLIP_PARAM_CH3, - CLIP_PARAM_CH4, - CLIP_PATTERN, - CLIP_CHANNEL, -} ClipboardType; - -typedef struct Clipboard { - ClipboardType type; - u8 src_pat; - u8 src_chan; - u8 src_trig; -} Clipboard; - -static Clipboard clipboard = {CLIP_EMPTY, 0, 0, 0}; - -void -save_bank(int i) { - sram_write(&patterns, sizeof(Metadata) + i * sizeof(patterns), sizeof(patterns)); -} - -void -load_bank(int i) { - sram_read(&patterns, sizeof(Metadata) + i * sizeof(patterns), sizeof(patterns)); -} - -// -// Channel render functions. -// - -void -draw_channels(void) { - // Contains 5 channel buttons: Ch. 1-4 + FM. We are only drawing the DMG - // channels for now, since FM may take some time to develop. - Tile *channel_tiles = ASSETS_CHANNEL_BUTTONS; - size_t k = 0; - 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_tile(CHAN_START_X, y, channel_tiles + k++, clr, false); - // draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, clr, false); - // draw_tile(CHAN_START_X + 16, y, channel_tiles + k++, clr, 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 + 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; - Tile *tiles = ASSETS_NOTE_NAMES; - tiles += 2 * trig.note; - // draw_tile(x, y, tiles, COL_FG, true); - // draw_tile(x + 8, y, tiles + 1, COL_FG, true); - } 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; - } -} +void set_time(int bpm); void irq_timer(void) { @@ -1901,20 +174,6 @@ get_current_trig(void) { return NULL; } -// Input handling works using a FSM. The input handler is switched to whichever -// function controls each section. For example, channel selection or trigger -// selection. -void (*input_handler)(void); - -void handle_trigger_selection(void); -void handle_channel_selection(void); -void handle_pattern_selection(void); -void handle_param_selection_sq1(void); -void handle_param_selection_sq2(void); -void handle_param_selection_wave(void); -void handle_param_selection_noise(void); -void handle_right_col_selection(void); - void handle_channel_selection(void) { if (key_tap(KEY_B)) { @@ -2623,302 +882,6 @@ handle_trigger_selection(void) { } } -void -clipboard_paste(void) { - Pattern *pat_dst = &patterns[pattern_selection_loc]; - Pattern *pat_src = &patterns[clipboard.src_pat]; - - if (input_handler == handle_trigger_selection) { - if (clipboard.type == CLIP_TRIG) { - // Copy notes or parameters when applicable. - switch (clipboard.src_chan) { - case 0: { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - } break; - case 1: { - pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - } break; - case 2: { - pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - } break; - case 3: { - pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch1.notes[clipboard.src_trig]; - } break; - } - } break; - case 1: { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; - pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; - pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; - pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; - } break; - case 1: { - pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; - } break; - case 2: { - pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - } break; - case 3: { - pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch2.notes[clipboard.src_trig]; - } break; - } - } break; - case 2: { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - } break; - case 1: { - pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - } break; - case 2: { - pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; - } break; - case 3: { - pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch3.notes[clipboard.src_trig]; - } break; - } - } break; - case 3: { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - } break; - case 1: { - pat_dst->ch2.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - } break; - case 2: { - pat_dst->ch3.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - } break; - case 3: { - pat_dst->ch4.notes[trig_selection_loc] = pat_src->ch4.notes[clipboard.src_trig]; - pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; - } break; - } - } break; - } - } - // Only paste the params for the respective trigger. - if (clipboard.type == CLIP_PARAM_CH1) { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - } break; - case 1: { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - } break; - } - } - if (clipboard.type == CLIP_PARAM_CH2) { - switch (channel_selection_loc) { - case 0: { - pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; - pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; - pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; - pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; - } break; - case 1: { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; - } break; - } - } - if (clipboard.type == CLIP_PARAM_CH3 && channel_selection_loc == clipboard.src_chan) { - pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; - } - if (clipboard.type == CLIP_PARAM_CH4 && channel_selection_loc == clipboard.src_chan) { - pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; - } - draw_triggers(); - draw_parameters(); - } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH1) { - pat_dst->ch1.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - draw_parameters(); - } else if (input_handler == handle_param_selection_sq1 && clipboard.type == CLIP_PARAM_CH2) { - pat_dst->ch1.params[trig_selection_loc].env_volume = pat_src->ch2.params[clipboard.src_trig].env_volume; - pat_dst->ch1.params[trig_selection_loc].env_time = pat_src->ch2.params[clipboard.src_trig].env_time; - pat_dst->ch1.params[trig_selection_loc].env_direction = pat_src->ch2.params[clipboard.src_trig].env_direction; - pat_dst->ch1.params[trig_selection_loc].duty_cycle = pat_src->ch2.params[clipboard.src_trig].duty_cycle; - draw_parameters(); - } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH2) { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch2.params[clipboard.src_trig]; - draw_parameters(); - } else if (input_handler == handle_param_selection_sq2 && clipboard.type == CLIP_PARAM_CH1) { - pat_dst->ch2.params[trig_selection_loc] = pat_src->ch1.params[clipboard.src_trig]; - draw_parameters(); - } else if (input_handler == handle_param_selection_wave && clipboard.type == CLIP_PARAM_CH3) { - pat_dst->ch3.params[trig_selection_loc] = pat_src->ch3.params[clipboard.src_trig]; - draw_parameters(); - } else if (input_handler == handle_param_selection_noise && clipboard.type == CLIP_PARAM_CH4) { - pat_dst->ch4.params[trig_selection_loc] = pat_src->ch4.params[clipboard.src_trig]; - draw_parameters(); - } else if (input_handler == handle_channel_selection && clipboard.type == CLIP_CHANNEL) { - // Copy notes from a different channel OR notes and parameters - // from a different pattern. - if (clipboard.src_chan == channel_selection_loc) { - switch (clipboard.src_chan) { - case 0: { pat_dst->ch1 = pat_src->ch1; } break; - case 1: { pat_dst->ch2 = pat_src->ch2; } break; - case 2: { pat_dst->ch3 = pat_src->ch3; } break; - case 3: { pat_dst->ch4 = pat_src->ch4; } break; - } - } else { - switch (clipboard.src_chan) { - case 0: { - switch (channel_selection_loc) { - case 0: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch1.notes[i] = pat_src->ch1.notes[i]; - } - } break; - case 1: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch2.notes[i] = pat_src->ch1.notes[i]; - } - } break; - case 2: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch3.notes[i] = pat_src->ch1.notes[i]; - } - } break; - case 3: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch4.notes[i] = pat_src->ch1.notes[i]; - } - } break; - } - } break; - case 1: { - switch (channel_selection_loc) { - case 0: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch1.notes[i] = pat_src->ch2.notes[i]; - } - } break; - case 1: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch2.notes[i] = pat_src->ch2.notes[i]; - } - } break; - case 2: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch3.notes[i] = pat_src->ch2.notes[i]; - } - } break; - case 3: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch4.notes[i] = pat_src->ch2.notes[i]; - } - } break; - } - } break; - case 2: { - switch (channel_selection_loc) { - case 0: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch1.notes[i] = pat_src->ch3.notes[i]; - } - } break; - case 1: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch2.notes[i] = pat_src->ch3.notes[i]; - } - } break; - case 2: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch3.notes[i] = pat_src->ch3.notes[i]; - } - } break; - case 3: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch4.notes[i] = pat_src->ch3.notes[i]; - } - } break; - } - } break; - case 3: { - switch (channel_selection_loc) { - case 0: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch1.notes[i] = pat_src->ch4.notes[i]; - } - } break; - case 1: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch2.notes[i] = pat_src->ch4.notes[i]; - } - } break; - case 2: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch3.notes[i] = pat_src->ch4.notes[i]; - } - } break; - case 3: { - for (size_t i = 0; i < 16; i++) { - pat_dst->ch4.notes[i] = pat_src->ch4.notes[i]; - } - } break; - } - } break; - } - } - draw_channels(); - draw_triggers(); - } else if (input_handler == handle_pattern_selection && clipboard.type == CLIP_PATTERN) { - // Copy an entire pattern. - if (pattern_selection_loc != clipboard.src_pat) { - *pat_dst = *pat_src; - draw_channels(); - draw_triggers(); - } - } -} - -void -clipboard_copy(void) { - if (input_handler == handle_trigger_selection) { - clipboard.type = CLIP_TRIG; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - clipboard.src_trig = trig_selection_loc; - } else if (input_handler == handle_param_selection_sq1) { - clipboard.type = CLIP_PARAM_CH1; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - clipboard.src_trig = trig_selection_loc; - } else if (input_handler == handle_param_selection_sq2) { - clipboard.type = CLIP_PARAM_CH2; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - clipboard.src_trig = trig_selection_loc; - } else if (input_handler == handle_param_selection_wave) { - clipboard.type = CLIP_PARAM_CH3; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - clipboard.src_trig = trig_selection_loc; - } else if (input_handler == handle_param_selection_noise) { - clipboard.type = CLIP_PARAM_CH4; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - clipboard.src_trig = trig_selection_loc; - } else if (input_handler == handle_channel_selection) { - clipboard.type = CLIP_CHANNEL; - clipboard.src_pat = pattern_selection_loc; - clipboard.src_chan = channel_selection_loc; - } else if (input_handler == handle_pattern_selection) { - clipboard.type = CLIP_PATTERN; - clipboard.src_pat = pattern_selection_loc; - } -} - void handle_sequencer_input(void) { if (key_tap(KEY_START)) { @@ -2943,18 +906,8 @@ handle_sequencer_input(void) { } } -void -load_assets(void) { - unpack_tiles(note_names, ASSETS_NOTE_NAMES, N_TILES_NOTE_NAMES); - unpack_tiles(channel_buttons, ASSETS_CHANNEL_BUTTONS, N_TILES_CHAN_BTSN); - unpack_tiles(default_wave_buttons, ASSETS_DEFAULT_WAVES, N_TILES_WAVE_BTNS); -} - void sequencer_init(void) { - // Unpack non-sprite tiles directly on the VRAM. - load_assets(); - // Load the previous bank from SRAM or initialize it if needed. sram_read(&metadata, 0, sizeof(Metadata)); if (metadata.magic != 0xbadd10de) { @@ -2972,28 +925,8 @@ sequencer_init(void) { load_bank(metadata.current_bank); } - // Initialize background objects and sprites. - draw_triggers(); - draw_channels(); - draw_piano(); - TriggerNote *trig = get_current_trig(); - draw_note(trig->note, COL_NOTE_PRESSED); - - // Draw screen border frame. - draw_rect(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 1); - // Initialize input handler. input_handler = handle_trigger_selection; - draw_trig_cursor(trig_selection_loc, COL_CURSOR); - draw_channel_cursor(channel_selection_loc, COL_GREY); - draw_pattern_cursor(pattern_selection_loc, COL_GREY); - draw_current_step(COL_RED); - draw_parameters(); - draw_bpm(); - draw_play(); - draw_stop(); - draw_pattern_buttons(); - draw_bank_buttons(); // Initialize sound system. SOUND_STATUS = SOUND_ENABLE; -- cgit v1.2.1