From 53c1e688f2b2f559a2bde556c9762519efa66f03 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 2 May 2021 17:06:03 +0200 Subject: Add sprites for envelope volume control --- src/sequencer.c | 198 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 145 insertions(+), 53 deletions(-) diff --git a/src/sequencer.c b/src/sequencer.c index f459d0f..39f083f 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -99,32 +99,74 @@ u32 sprite_trigger_selection[] = { 0x04040407, 0x00000000, 0x00000000, 0x00000000, }; +u32 sprite_env_labels[] = { + // Volume. + 0xa0a0a0a0, 0xc0000000, 0x262a2a2a, 0xee000000, + 0xaaeaaaaa, 0xae000000, 0x0e020602, 0x0e000000, +}; + +u32 sprite_env_volume[] = { + 0x80808080, 0x80808000, 0x0f0c0c0c, 0x0c6c6f00, + 0x1f999919, 0x19999f00, 0x00090d06, 0x030d0c00, + 0x80808080, 0x80808000, 0x0f01010f, 0x09696f00, + 0x1f83831f, 0x13939f00, 0x00090d06, 0x030d0c00, + 0x60606060, 0x60606000, 0x1f18181e, 0x18d8df00, + 0x3e30303c, 0x30303e00, 0x00131b0c, 0x061b1900, + 0xf8c0c0f8, 0x1818f800, 0x3e06063e, 0x26a6be00, + 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200, + 0xf8c0c0f8, 0x1818f800, 0x3e323232, 0x32b2be00, + 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200, + 0xf8c0c0f0, 0xc0c0f800, 0x3e30303c, 0x30b0be00, + 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200, + 0xc0e0d0c8, 0xf8c0c000, 0x3e323232, 0x32b2be00, + 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200, + 0xc0e0d0c8, 0xf8c0c000, 0x3e06063e, 0x26a6be00, + 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200, + 0xf81818f8, 0xc0c0f800, 0x3e30303c, 0x30b0be00, + 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200, + 0xf81818f8, 0x9898f800, 0x3e323232, 0x32b2be00, + 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200, + 0xf81818f8, 0x9898f800, 0x3e06063e, 0x26a6be00, + 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200, + 0xf8c0c060, 0x30181800, 0x3e30303c, 0x30b0be00, + 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200, + 0xf8c8c8f8, 0xc8c8f800, 0x3e323232, 0x32b2be00, + 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200, + 0xf8c8c8f8, 0xc8c8f800, 0x3e06063e, 0x26a6be00, + 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200, + 0xf8c8c8f8, 0xc0c0f800, 0x3e30303c, 0x30b0be00, + 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200, + 0xec2c2c2c, 0x2c2cec00, 0xfbcbcbcb, 0xcbcbfb00, + 0xf0909090, 0x9096f600, 0x0199d961, 0x31d9c900, +}; + typedef struct SeqTrigger { bool trigger; Note note; + u8 env_volume; // TODO: ... } SeqTrigger; static SeqTrigger sequence_synth[] = { - {true, NOTE_D_4}, - {true, NOTE_F_4}, - {true, NOTE_A_4}, - {true, NOTE_C_5}, - - {true, NOTE_D_4}, - {false, NOTE_C_SHARP_4}, - {false, NOTE_D_4}, - {false, NOTE_D_4}, - - {true, NOTE_D_4}, - {true, NOTE_F_4}, - {true, NOTE_A_4}, - {true, NOTE_C_5}, - - {true, NOTE_D_4}, - {false, NOTE_D_4}, - {true, NOTE_A_4}, - {false, NOTE_A_5}, + {true, NOTE_D_4, 0}, + {true, NOTE_F_4, 1}, + {true, NOTE_A_4, 2}, + {true, NOTE_C_5, 3}, + + {true, NOTE_D_4, 4}, + {false, NOTE_C_SHARP_4, 5}, + {false, NOTE_D_4, 6}, + {false, NOTE_D_4, 7}, + + {true, NOTE_D_4, 8}, + {true, NOTE_F_4, 9}, + {true, NOTE_A_4, 10}, + {true, NOTE_C_5, 11}, + + {true, NOTE_D_4, 12}, + {false, NOTE_D_4, 13}, + {true, NOTE_A_4, 14}, + {false, NOTE_A_5, 15}, }; static int bpm = 120; @@ -133,9 +175,12 @@ static Note active_note; void irq_timer_0(void) { - active_note = sequence_synth[step_counter].note; - if (sequence_synth[step_counter].trigger) { - SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(13) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_DUTY(2); + SeqTrigger *trig = &sequence_synth[step_counter]; + active_note = trig->note; + if (trig->trigger) { + SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume) + | SOUND_SQUARE_ENV_TIME(4) + | SOUND_SQUARE_DUTY(2); SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; } step_counter = (step_counter + 1) % 16; @@ -161,46 +206,56 @@ set_time(int bpm) { // // Currently we load all sequencer sprite memory in the VRAM: // -// - Note names: 73x2 tiles -// - Sprite trigger button: 8 tiles -// - Duration indicator (TODO) -// - Current step marker. +// - Note names: 73x2 tiles. +// - Sprite trigger button: 8 tiles. +// - Current step marker: 1 tile. +// - Selected trigger marker: 16 tile. +// - Env: Volume label: 4 tiles. +// - Env: Volume text: 7x4 tiles +// - (TODO) Duration indicator // // The order of OBJs correspond to: // // - 000-015 step note names. -// - 015-029 step trigger steps. -// - 030-045 step duration indicators. -// - 046-046 current step marker. -// - 047-047 trigger selection indicator. +// - 015-031 step trigger steps. +// - 032-032 current step marker. +// - 033-033 trigger selection indicator. +// - 034-034 envelope: volume label. +// - 035-0xx envelope: volume indicator. // + +// Positioning parameters. +#define SEQ_TRIG_POS_X 45 +#define SEQ_TRIG_POS_Y 50 +#define SEQ_TRIG_DIST 20 +#define SEQ_ENV_POS_X 10 +#define SEQ_ENV_POS_Y 10 + size_t obj_counter = 0; typedef struct SeqSprite { u8 id; int x; int y; + size_t base_tile; u16 obj_attr_0; u16 obj_attr_1; u16 obj_attr_2; } SeqSprite; -#define SEQ_POS_X 45 -#define SEQ_POS_Y 50 -#define SEQ_TRIG_DIST 20 - int trig_selection_loc = 1; -SeqSprite seq_sprites[34] = {0}; +SeqSprite seq_sprites[36] = {0}; void init_sequencer_sprites(void) { // Sprite note names. size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73); for (size_t i = 0; i < 16; ++i) { - int x = SEQ_POS_X + i * SEQ_TRIG_DIST; - int y = SEQ_POS_Y; + int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST; + int y = SEQ_TRIG_POS_Y; + int base_tile = sprites[sprite_id].tile_start; if (i >= 8) { y += 32; x -= 8 * SEQ_TRIG_DIST; @@ -209,52 +264,81 @@ init_sequencer_sprites(void) { seq_sprites[i].y = y; seq_sprites[i].id = obj_counter++; + seq_sprites[i].base_tile = base_tile; seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); // TODO: They should start hidden until the update function changes that. // seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_HIDDEN; seq_sprites[i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); - seq_sprites[i].obj_attr_2 = sprites[sprite_id].tile_start; + seq_sprites[i].obj_attr_2 = base_tile; } // Trigger boxes. sprite_id = load_packed_sprite_data(&sprite_trigger_button, 8, 1); for (size_t i = 0; i < 16; ++i) { - int x = SEQ_POS_X + i * SEQ_TRIG_DIST; - int y = SEQ_POS_Y; + int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST; + int y = SEQ_TRIG_POS_Y; + int base_tile = sprites[sprite_id].tile_start; if (i >= 8) { y += 32; x -= 8 * SEQ_TRIG_DIST; } seq_sprites[i + 16].id = obj_counter++; + seq_sprites[i + 16].base_tile = base_tile; seq_sprites[i + 16].obj_attr_0 = OBJ_SHAPE_TALL | OBJ_Y_COORD(y); seq_sprites[i + 16].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); - seq_sprites[i + 16].obj_attr_2 = sprites[sprite_id].tile_start; + seq_sprites[i + 16].obj_attr_2 = base_tile; } sprite_id = load_packed_sprite_data(&sprite_trigger_active_indicator, 1, 1); - // TODO: No need for a for loop. { - int x = SEQ_POS_X; - int y = SEQ_POS_Y + 15; + int x = SEQ_TRIG_POS_X; + int y = SEQ_TRIG_POS_Y + 15; + int base_tile = sprites[sprite_id].tile_start; seq_sprites[32].id = obj_counter++; + seq_sprites[32].base_tile = base_tile; seq_sprites[32].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); - seq_sprites[32].obj_attr_2 = sprites[sprite_id].tile_start | OBJ_PAL_BANK(1); + seq_sprites[32].obj_attr_2 = base_tile | OBJ_PAL_BANK(1); } sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); - // TODO: No need for a for loop. { - int x = SEQ_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; - int y = SEQ_POS_Y - 2; + int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; + int y = SEQ_TRIG_POS_Y - 2; + int base_tile = sprites[sprite_id].tile_start; if (trig_selection_loc >= 8) { y += 32; x -= 8 * SEQ_TRIG_DIST; } seq_sprites[33].id = obj_counter++; + seq_sprites[33].base_tile = base_tile; seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); - seq_sprites[33].obj_attr_2 = sprites[sprite_id].tile_start | OBJ_PAL_BANK(2); + seq_sprites[33].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); + } + + sprite_id = load_packed_sprite_data(&sprite_env_labels, 4, 1); + { + int x = SEQ_ENV_POS_X; + int y = SEQ_ENV_POS_Y; + int base_tile = sprites[sprite_id].tile_start; + seq_sprites[34].id = obj_counter++; + seq_sprites[34].base_tile = base_tile; + seq_sprites[34].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[34].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); + seq_sprites[34].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); + } + + sprite_id = load_packed_sprite_data(&sprite_env_volume, 4, 16); + { + int x = SEQ_ENV_POS_X; + int y = SEQ_ENV_POS_Y + 8; + int base_tile = sprites[sprite_id].tile_start; + seq_sprites[35].id = obj_counter++; + seq_sprites[35].base_tile = base_tile; + seq_sprites[35].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[35].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); + seq_sprites[35].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } } @@ -279,8 +363,8 @@ update_sequencer_sprites(void) { // 33: Sequence indicator. { - int x = SEQ_POS_X + step_counter * SEQ_TRIG_DIST + 3; - int y = SEQ_POS_Y + 15; + int x = SEQ_TRIG_POS_X + step_counter * SEQ_TRIG_DIST + 3; + int y = SEQ_TRIG_POS_Y + 15; if (step_counter >= 8) { y += 32; x -= 8 * SEQ_TRIG_DIST; @@ -291,8 +375,8 @@ update_sequencer_sprites(void) { // 34: Trigger selection. { - int x = SEQ_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; - int y = SEQ_POS_Y - 2; + int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; + int y = SEQ_TRIG_POS_Y - 2; if (trig_selection_loc >= 8) { y += 32; x -= 8 * SEQ_TRIG_DIST; @@ -301,6 +385,14 @@ update_sequencer_sprites(void) { seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); } + + // 36: Envelope initial volume + { + size_t tile_diff = sequence_synth[trig_selection_loc].env_volume * 4; + size_t base_tile = seq_sprites[35].base_tile; + size_t tile = base_tile + tile_diff; + seq_sprites[35].obj_attr_2 = tile | OBJ_PAL_BANK(2); + } } void -- cgit v1.2.1