diff options
Diffstat (limited to 'src/sequencer.c')
-rw-r--r-- | src/sequencer.c | 285 |
1 files changed, 212 insertions, 73 deletions
diff --git a/src/sequencer.c b/src/sequencer.c index 0c6181f..ae06031 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -1,3 +1,20 @@ | |||
1 | // Positioning parameters. | ||
2 | #define SEQ_TRIG_POS_X 45 | ||
3 | #define SEQ_TRIG_POS_Y 50 | ||
4 | #define SEQ_TRIG_DIST_X 18 | ||
5 | #define SEQ_TRIG_DIST_Y 28 | ||
6 | #define SEQ_CHANNEL_POS_X SEQ_TRIG_POS_X - 32 | ||
7 | #define SEQ_CHANNEL_POS_Y SEQ_TRIG_POS_Y | ||
8 | #define SEQ_CHANNEL_DIST_Y 11 | ||
9 | #define SEQ_ENV_POS_X 10 | ||
10 | #define SEQ_ENV_POS_Y 10 | ||
11 | #define SEQ_ENV_DIST 32 | ||
12 | #define SEQ_DUTYCYCLE_POS_X SEQ_ENV_POS_X + SEQ_ENV_DIST * 3 | ||
13 | #define SEQ_DUTYCYCLE_POS_Y 10 - 8 | ||
14 | #define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST | ||
15 | #define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y | ||
16 | #define SEQ_N_CHANNELS 2 | ||
17 | |||
1 | u32 sprite_note_names[] = { | 18 | u32 sprite_note_names[] = { |
2 | 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e, | 19 | 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e, |
3 | 0x00000098, 0xa8a8a898, 0x00000038, 0x203b0a39, | 20 | 0x00000098, 0xa8a8a898, 0x00000038, 0x203b0a39, |
@@ -223,6 +240,25 @@ u32 sprite_synth_param_selector[] = { | |||
223 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | 240 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
224 | }; | 241 | }; |
225 | 242 | ||
243 | u32 sprite_channels[] = { | ||
244 | 0xc0404040, 0x404040c0, 0xff005c44, 0xc45c00ff, | ||
245 | 0xff002121, 0x212500ff, 0x03020202, 0x02020203, | ||
246 | 0xc0404040, 0x404040c0, 0xff00aea2, 0xe2ae00ff, | ||
247 | 0xff005050, 0x505200ff, 0x03020202, 0x02020203, | ||
248 | 0xc0404040, 0x404040c0, 0xff005751, 0x715700ff, | ||
249 | 0xff00a8a8, 0xa8a900ff, 0x03020202, 0x02020203, | ||
250 | 0xc0404040, 0x404040c0, 0xff005751, 0x715700ff, | ||
251 | 0xff00a8a8, 0xa8c900ff, 0x03020202, 0x02020203, | ||
252 | 0xc0404040, 0x404040c0, 0xff007010, 0x301000ff, | ||
253 | 0xff000507, 0x050500ff, 0x03020202, 0x02020203, | ||
254 | }; | ||
255 | |||
256 | u32 sprite_channels_selector[] = { | ||
257 | 0x70101000, 0x00000000, 0x00000000, 0x00000000, | ||
258 | 0x00000000, 0x00000000, 0x0e080800, 0x00000000, | ||
259 | 0x00101070, 0x00000000, 0x00000000, 0x00000000, | ||
260 | 0x00000000, 0x00000000, 0x0008080e, 0x00000000, | ||
261 | }; | ||
226 | 262 | ||
227 | typedef struct SeqTrigger { | 263 | typedef struct SeqTrigger { |
228 | bool trigger; | 264 | bool trigger; |
@@ -234,32 +270,39 @@ typedef struct SeqTrigger { | |||
234 | u8 sweep_number; | 270 | u8 sweep_number; |
235 | u8 sweep_time; | 271 | u8 sweep_time; |
236 | u8 sweep_direction; | 272 | u8 sweep_direction; |
237 | // TODO: ... | 273 | // TODO: Do we need other fields? |
238 | } SeqTrigger; | 274 | } SeqTrigger; |
239 | 275 | ||
240 | static SeqTrigger sequence_synth[] = { | 276 | static SeqTrigger sequence_synth[16] = { |
241 | {true , NOTE_D_4 , 0, 0, 0, 0, 0, 0, 0}, | 277 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
242 | {true , NOTE_F_4 , 1, 1, 0, 0, 1, 1, 0}, | 278 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
243 | {true , NOTE_A_4 , 2, 2, 0, 1, 2, 2, 1}, | 279 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
244 | {true , NOTE_C_5 , 3, 3, 0, 1, 3, 3, 1}, | 280 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
245 | 281 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, | |
246 | {true , NOTE_D_4 , 4, 4, 1, 2, 4, 4, 0}, | 282 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
247 | {false , NOTE_C_SHARP_4 , 5, 5, 1, 2, 5, 5, 0}, | 283 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
248 | {false , NOTE_D_4 , 6, 6, 1, 3, 6, 6, 1}, | 284 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
249 | {false , NOTE_D_4 , 7, 7, 1, 3, 7, 7, 1}, | 285 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
250 | 286 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, | |
251 | {true , NOTE_D_4 , 8, 0, 0, 0, 7, 0, 0}, | 287 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
252 | {true , NOTE_F_4 , 9, 1, 0, 0, 6, 1, 0}, | 288 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
253 | {true , NOTE_A_4 , 10, 2, 0, 1, 5, 2, 1}, | 289 | {true, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
254 | {true , NOTE_C_5 , 11, 3, 0, 1, 4, 3, 1}, | 290 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
255 | 291 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, | |
256 | {true , NOTE_D_4 , 12, 4, 1, 2, 3, 4, 0}, | 292 | {false, NOTE_C_4, 8, 4, 0, 2, 0, 0, 0}, |
257 | {false , NOTE_D_4 , 13, 5, 1, 2, 2, 5, 0}, | ||
258 | {true , NOTE_A_4 , 14, 6, 1, 3, 1, 6, 1}, | ||
259 | {false , NOTE_A_5 , 15, 7, 1, 3, 0, 7, 1}, | ||
260 | }; | 293 | }; |
261 | 294 | ||
262 | static int bpm = 120; | 295 | // TODO: Support for copy paste anything, contextual. If we are on trigger |
296 | // selection mode, pressing the copy key (SELECT? SELECT+B?), all synth | ||
297 | // parameters will be copied for that trigger. Pressing paste (SELECT+A?) will | ||
298 | // update the params. This only works on compatible channels (Not on the wave | ||
299 | // channel for example). If an entire channel is copied, all trigs in the | ||
300 | // sequence will be copied. We can choose to copy only one of the parameters as | ||
301 | // well or the note/duration. | ||
302 | // TODO: Allow muting and unmuting channels. Show in grey when muted. | ||
303 | // TODO: Show channel beat indicator if a note is being played. | ||
304 | |||
305 | static int bpm = 180; | ||
263 | static int step_counter = 0; | 306 | static int step_counter = 0; |
264 | static Note active_note; | 307 | static Note active_note; |
265 | 308 | ||
@@ -335,21 +378,15 @@ set_time(int bpm) { | |||
335 | // - 048-048 sweep: direction indicator. | 378 | // - 048-048 sweep: direction indicator. |
336 | // - 049-049 sweep: sweep label. | 379 | // - 049-049 sweep: sweep label. |
337 | // - 050-050 synth parameter selector. | 380 | // - 050-050 synth parameter selector. |
381 | // - 051-051 channel 1. | ||
382 | // - 052-052 channel 2. | ||
383 | // - 053-053 channel 3. | ||
384 | // - 054-054 channel 4. | ||
385 | // - 055-055 RESERVED: FM synth?. | ||
386 | // - 056-056 channel selector. | ||
338 | // | 387 | // |
339 | 388 | ||
340 | 389 | ||
341 | // Positioning parameters. | ||
342 | #define SEQ_TRIG_POS_X 45 | ||
343 | #define SEQ_TRIG_POS_Y 50 | ||
344 | #define SEQ_TRIG_DIST 20 | ||
345 | #define SEQ_ENV_POS_X 10 | ||
346 | #define SEQ_ENV_POS_Y 10 | ||
347 | #define SEQ_ENV_DIST 32 | ||
348 | #define SEQ_DUTYCYCLE_POS_X SEQ_ENV_POS_X + SEQ_ENV_DIST * 3 | ||
349 | #define SEQ_DUTYCYCLE_POS_Y 10 - 8 | ||
350 | #define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST | ||
351 | #define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y | ||
352 | |||
353 | size_t obj_counter = 0; | 390 | size_t obj_counter = 0; |
354 | 391 | ||
355 | typedef struct SeqSprite { | 392 | typedef struct SeqSprite { |
@@ -365,14 +402,16 @@ typedef struct SeqSprite { | |||
365 | 402 | ||
366 | typedef enum { | 403 | typedef enum { |
367 | SEQ_SELECT_TRIGGER, | 404 | SEQ_SELECT_TRIGGER, |
405 | SEQ_SELECT_CHANNEL, | ||
368 | SEQ_SELECT_PARAMETER, | 406 | SEQ_SELECT_PARAMETER, |
369 | } SeqSelect; | 407 | } SeqSelect; |
370 | 408 | ||
371 | int trig_selection_loc = 0; | 409 | int trig_selection_loc = 0; |
372 | int param_selection_loc = 0; | 410 | int param_selection_loc = 0; |
411 | int channel_selection_loc = 0; | ||
373 | SeqSelect current_selection = SEQ_SELECT_TRIGGER; | 412 | SeqSelect current_selection = SEQ_SELECT_TRIGGER; |
374 | 413 | ||
375 | SeqSprite seq_sprites[51] = {0}; | 414 | SeqSprite seq_sprites[57] = {0}; |
376 | 415 | ||
377 | void | 416 | void |
378 | init_sequencer_sprites(void) { | 417 | init_sequencer_sprites(void) { |
@@ -386,12 +425,12 @@ init_sequencer_sprites(void) { | |||
386 | // Sprite note names. | 425 | // Sprite note names. |
387 | size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73); | 426 | size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73); |
388 | for (size_t i = 0; i < 16; ++i) { | 427 | for (size_t i = 0; i < 16; ++i) { |
389 | int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST; | 428 | int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST_X; |
390 | int y = SEQ_TRIG_POS_Y; | 429 | int y = SEQ_TRIG_POS_Y; |
391 | int base_tile = sprites[sprite_id].tile_start; | 430 | int base_tile = sprites[sprite_id].tile_start; |
392 | if (i >= 8) { | 431 | if (i >= 8) { |
393 | y += 32; | 432 | y += SEQ_TRIG_DIST_Y; |
394 | x -= 8 * SEQ_TRIG_DIST; | 433 | x -= 8 * SEQ_TRIG_DIST_X; |
395 | } | 434 | } |
396 | seq_sprites[i].x = x; | 435 | seq_sprites[i].x = x; |
397 | seq_sprites[i].y = y; | 436 | seq_sprites[i].y = y; |
@@ -406,12 +445,12 @@ init_sequencer_sprites(void) { | |||
406 | // Trigger boxes. | 445 | // Trigger boxes. |
407 | sprite_id = load_packed_sprite_data(&sprite_trigger_button, 8, 1); | 446 | sprite_id = load_packed_sprite_data(&sprite_trigger_button, 8, 1); |
408 | for (size_t i = 0; i < 16; ++i) { | 447 | for (size_t i = 0; i < 16; ++i) { |
409 | int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST; | 448 | int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST_X; |
410 | int y = SEQ_TRIG_POS_Y; | 449 | int y = SEQ_TRIG_POS_Y; |
411 | int base_tile = sprites[sprite_id].tile_start; | 450 | int base_tile = sprites[sprite_id].tile_start; |
412 | if (i >= 8) { | 451 | if (i >= 8) { |
413 | y += 32; | 452 | y += 28; |
414 | x -= 8 * SEQ_TRIG_DIST; | 453 | x -= 8 * SEQ_TRIG_DIST_X; |
415 | } | 454 | } |
416 | seq_sprites[i + 16].id = obj_counter++; | 455 | seq_sprites[i + 16].id = obj_counter++; |
417 | seq_sprites[i + 16].base_tile = base_tile; | 456 | seq_sprites[i + 16].base_tile = base_tile; |
@@ -434,12 +473,12 @@ init_sequencer_sprites(void) { | |||
434 | 473 | ||
435 | sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); | 474 | sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); |
436 | { | 475 | { |
437 | int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; | 476 | int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST_X; |
438 | int y = SEQ_TRIG_POS_Y - 2; | 477 | int y = SEQ_TRIG_POS_Y - 2; |
439 | int base_tile = sprites[sprite_id].tile_start; | 478 | int base_tile = sprites[sprite_id].tile_start; |
440 | if (trig_selection_loc >= 8) { | 479 | if (trig_selection_loc >= 8) { |
441 | y += 32; | 480 | y += SEQ_TRIG_DIST_Y; |
442 | x -= 8 * SEQ_TRIG_DIST; | 481 | x -= 8 * SEQ_TRIG_DIST_X; |
443 | } | 482 | } |
444 | seq_sprites[33].id = obj_counter++; | 483 | seq_sprites[33].id = obj_counter++; |
445 | seq_sprites[33].base_tile = base_tile; | 484 | seq_sprites[33].base_tile = base_tile; |
@@ -643,6 +682,72 @@ init_sequencer_sprites(void) { | |||
643 | seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); | 682 | seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); |
644 | seq_sprites[50].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); | 683 | seq_sprites[50].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); |
645 | } | 684 | } |
685 | |||
686 | sprite_id = load_packed_sprite_data(&sprite_channels, 4, 5); | ||
687 | { | ||
688 | int x = SEQ_CHANNEL_POS_X; | ||
689 | int y = SEQ_CHANNEL_POS_Y; | ||
690 | int base_tile = sprites[sprite_id].tile_start; | ||
691 | seq_sprites[51].id = obj_counter++; | ||
692 | seq_sprites[51].base_tile = base_tile; | ||
693 | seq_sprites[51].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); | ||
694 | seq_sprites[51].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); | ||
695 | seq_sprites[51].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); | ||
696 | } | ||
697 | { | ||
698 | int x = SEQ_CHANNEL_POS_X; | ||
699 | int y = SEQ_CHANNEL_POS_Y + SEQ_CHANNEL_DIST_Y; | ||
700 | int base_tile = sprites[sprite_id].tile_start + 4; | ||
701 | seq_sprites[52].id = obj_counter++; | ||
702 | seq_sprites[52].base_tile = base_tile; | ||
703 | seq_sprites[52].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); | ||
704 | seq_sprites[52].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); | ||
705 | seq_sprites[52].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); | ||
706 | } | ||
707 | { | ||
708 | int x = SEQ_CHANNEL_POS_X; | ||
709 | int y = SEQ_CHANNEL_POS_Y + SEQ_CHANNEL_DIST_Y * 2; | ||
710 | int base_tile = sprites[sprite_id].tile_start + 8; | ||
711 | seq_sprites[53].id = obj_counter++; | ||
712 | seq_sprites[53].base_tile = base_tile; | ||
713 | seq_sprites[53].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; | ||
714 | seq_sprites[53].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); | ||
715 | seq_sprites[53].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); | ||
716 | } | ||
717 | { | ||
718 | int x = SEQ_CHANNEL_POS_X; | ||
719 | int y = SEQ_CHANNEL_POS_Y + SEQ_CHANNEL_DIST_Y * 3; | ||
720 | int base_tile = sprites[sprite_id].tile_start + 12; | ||
721 | seq_sprites[54].id = obj_counter++; | ||
722 | seq_sprites[54].base_tile = base_tile; | ||
723 | seq_sprites[54].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; | ||
724 | seq_sprites[54].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); | ||
725 | seq_sprites[54].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); | ||
726 | } | ||
727 | { | ||
728 | int x = SEQ_CHANNEL_POS_X; | ||
729 | int y = SEQ_CHANNEL_POS_Y + SEQ_CHANNEL_DIST_Y * 4; | ||
730 | int base_tile = sprites[sprite_id].tile_start + 16; | ||
731 | seq_sprites[55].id = obj_counter++; | ||
732 | seq_sprites[55].base_tile = base_tile; | ||
733 | seq_sprites[55].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; | ||
734 | seq_sprites[55].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); | ||
735 | seq_sprites[55].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); | ||
736 | } | ||
737 | |||
738 | sprite_id = load_packed_sprite_data(&sprite_channels_selector, 8, 1); | ||
739 | { | ||
740 | int x = SEQ_CHANNEL_POS_X; | ||
741 | int y = SEQ_CHANNEL_POS_Y - 2; | ||
742 | int base_tile = sprites[sprite_id].tile_start; | ||
743 | seq_sprites[56].id = obj_counter++; | ||
744 | seq_sprites[56].base_tile = base_tile; | ||
745 | // TODO: Start hidden. | ||
746 | // seq_sprites[55].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; | ||
747 | seq_sprites[56].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); | ||
748 | seq_sprites[56].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); | ||
749 | seq_sprites[56].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); | ||
750 | } | ||
646 | } | 751 | } |
647 | 752 | ||
648 | void | 753 | void |
@@ -666,11 +771,11 @@ update_sequencer_sprites(void) { | |||
666 | 771 | ||
667 | // 33: Sequence indicator. | 772 | // 33: Sequence indicator. |
668 | { | 773 | { |
669 | int x = SEQ_TRIG_POS_X + step_counter * SEQ_TRIG_DIST + 3; | 774 | int x = SEQ_TRIG_POS_X + step_counter * SEQ_TRIG_DIST_X + 3; |
670 | int y = SEQ_TRIG_POS_Y + 15; | 775 | int y = SEQ_TRIG_POS_Y + 15; |
671 | if (step_counter >= 8) { | 776 | if (step_counter >= 8) { |
672 | y += 32; | 777 | y += SEQ_TRIG_DIST_Y; |
673 | x -= 8 * SEQ_TRIG_DIST; | 778 | x -= 8 * SEQ_TRIG_DIST_X; |
674 | } | 779 | } |
675 | seq_sprites[32].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); // TODO: Mask and update instead. | 780 | seq_sprites[32].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); // TODO: Mask and update instead. |
676 | seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); // TODO: Mask and update instead. | 781 | seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); // TODO: Mask and update instead. |
@@ -678,13 +783,20 @@ update_sequencer_sprites(void) { | |||
678 | 783 | ||
679 | // 34: Trigger selection. | 784 | // 34: Trigger selection. |
680 | { | 785 | { |
681 | int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; | 786 | int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST_X; |
682 | int y = SEQ_TRIG_POS_Y - 2; | 787 | int y = SEQ_TRIG_POS_Y - 2; |
683 | if (trig_selection_loc >= 8) { | 788 | if (trig_selection_loc >= 8) { |
684 | y += 32; | 789 | y += SEQ_TRIG_DIST_Y; |
685 | x -= 8 * SEQ_TRIG_DIST; | 790 | x -= 8 * SEQ_TRIG_DIST_X; |
791 | } | ||
792 | if (current_selection == SEQ_SELECT_TRIGGER | ||
793 | || current_selection == SEQ_SELECT_PARAMETER) { | ||
794 | seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); | ||
795 | } else { | ||
796 | seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | ||
797 | | OBJ_Y_COORD(y) | ||
798 | | OBJ_HIDDEN; | ||
686 | } | 799 | } |
687 | seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); | ||
688 | seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); | 800 | seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); |
689 | int base_tile = seq_sprites[33].base_tile; | 801 | int base_tile = seq_sprites[33].base_tile; |
690 | if (current_selection == SEQ_SELECT_TRIGGER) { | 802 | if (current_selection == SEQ_SELECT_TRIGGER) { |
@@ -757,10 +869,6 @@ update_sequencer_sprites(void) { | |||
757 | { | 869 | { |
758 | int x = SEQ_ENV_POS_X + 1 + (param_selection_loc % 7) * SEQ_ENV_DIST; | 870 | int x = SEQ_ENV_POS_X + 1 + (param_selection_loc % 7) * SEQ_ENV_DIST; |
759 | int y = SEQ_ENV_POS_Y - 3; | 871 | int y = SEQ_ENV_POS_Y - 3; |
760 | if (param_selection_loc >= 8) { | ||
761 | y += 32; | ||
762 | x -= 8 * SEQ_TRIG_DIST; | ||
763 | } | ||
764 | int hidden = 0; | 872 | int hidden = 0; |
765 | if (current_selection != SEQ_SELECT_PARAMETER) { | 873 | if (current_selection != SEQ_SELECT_PARAMETER) { |
766 | hidden = OBJ_HIDDEN; | 874 | hidden = OBJ_HIDDEN; |
@@ -768,40 +876,52 @@ update_sequencer_sprites(void) { | |||
768 | seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; | 876 | seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; |
769 | seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); | 877 | seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); |
770 | } | 878 | } |
879 | |||
880 | // 57: Parameter selector. | ||
881 | { | ||
882 | int x = SEQ_CHANNEL_POS_X; | ||
883 | int y = SEQ_CHANNEL_POS_Y - 2; | ||
884 | y += (channel_selection_loc % SEQ_N_CHANNELS * SEQ_CHANNEL_DIST_Y); | ||
885 | seq_sprites[56].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); | ||
886 | seq_sprites[56].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); | ||
887 | int base_tile = seq_sprites[56].base_tile; | ||
888 | if (current_selection == SEQ_SELECT_CHANNEL) { | ||
889 | seq_sprites[56].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); | ||
890 | } else { | ||
891 | seq_sprites[56].obj_attr_2 = base_tile | OBJ_PAL_BANK(3); | ||
892 | } | ||
893 | } | ||
771 | } | 894 | } |
772 | 895 | ||
773 | void | 896 | void |
774 | handle_sequencer_input(void) { | 897 | handle_sequencer_input(void) { |
775 | if (current_selection == SEQ_SELECT_TRIGGER) { | 898 | if (current_selection == SEQ_SELECT_TRIGGER) { |
776 | if (key_pressed(KEY_LEFT)) { | 899 | if (key_pressed(KEY_LEFT)) { |
777 | if (trig_selection_loc == 0) { | 900 | if (trig_selection_loc == 0 || trig_selection_loc == 8) { |
778 | trig_selection_loc = 15; | 901 | current_selection = SEQ_SELECT_CHANNEL; |
779 | } else { | 902 | } else { |
780 | trig_selection_loc = CLAMP(trig_selection_loc - 1, 0, 15); | 903 | trig_selection_loc = CLAMP(trig_selection_loc - 1, 0, 15); |
781 | } | 904 | } |
782 | } | 905 | } else if (key_pressed(KEY_RIGHT)) { |
783 | if (key_pressed(KEY_RIGHT)) { | ||
784 | if (trig_selection_loc == 15) { | 906 | if (trig_selection_loc == 15) { |
785 | trig_selection_loc = 0; | 907 | trig_selection_loc = 0; |
786 | } else { | 908 | } else { |
787 | trig_selection_loc = CLAMP(trig_selection_loc + 1, 0, 15); | 909 | trig_selection_loc = CLAMP(trig_selection_loc + 1, 0, 15); |
788 | } | 910 | } |
789 | } | 911 | } else if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) { |
790 | if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) { | ||
791 | trig_selection_loc = (trig_selection_loc + 8) % 16; | 912 | trig_selection_loc = (trig_selection_loc + 8) % 16; |
792 | } | 913 | } else if (key_pressed(KEY_B)) { |
793 | if (key_pressed(KEY_B)) { | ||
794 | sequence_synth[trig_selection_loc].trigger ^= 1; | 914 | sequence_synth[trig_selection_loc].trigger ^= 1; |
795 | } | 915 | } else if (key_pressed(KEY_L)) { |
796 | if (key_pressed(KEY_L)) { | 916 | sequence_synth[trig_selection_loc].note = CLAMP( |
797 | sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note - 1, NOTE_C_2, NOTE_C_8); | 917 | sequence_synth[trig_selection_loc].note - 1, |
798 | } | 918 | NOTE_C_2, NOTE_C_8); |
799 | if (key_pressed(KEY_R)) { | 919 | } else if (key_pressed(KEY_R)) { |
800 | sequence_synth[trig_selection_loc].note = CLAMP(sequence_synth[trig_selection_loc].note + 1, NOTE_C_2, NOTE_C_8); | 920 | sequence_synth[trig_selection_loc].note = CLAMP( |
801 | } | 921 | sequence_synth[trig_selection_loc].note + 1, |
802 | 922 | NOTE_C_2, NOTE_C_8); | |
803 | // Switch to parameter selection. | 923 | } else if (key_pressed(KEY_A)) { |
804 | if (key_pressed(KEY_A)) { | 924 | // Switch to parameter selection. |
805 | current_selection = SEQ_SELECT_PARAMETER; | 925 | current_selection = SEQ_SELECT_PARAMETER; |
806 | } | 926 | } |
807 | } else if (current_selection == SEQ_SELECT_PARAMETER) { | 927 | } else if (current_selection == SEQ_SELECT_PARAMETER) { |
@@ -896,6 +1016,25 @@ handle_sequencer_input(void) { | |||
896 | if (key_pressed(KEY_B)) { | 1016 | if (key_pressed(KEY_B)) { |
897 | sequence_synth[trig_selection_loc].trigger ^= 1; | 1017 | sequence_synth[trig_selection_loc].trigger ^= 1; |
898 | } | 1018 | } |
1019 | } else if (current_selection == SEQ_SELECT_CHANNEL) { | ||
1020 | if (key_pressed(KEY_RIGHT)) { | ||
1021 | current_selection = SEQ_SELECT_TRIGGER; | ||
1022 | trig_selection_loc = 0; | ||
1023 | } | ||
1024 | if (key_pressed(KEY_UP)) { | ||
1025 | if (channel_selection_loc == 0) { | ||
1026 | channel_selection_loc = 3; | ||
1027 | } else { | ||
1028 | channel_selection_loc = CLAMP(channel_selection_loc - 1, 0, 6); | ||
1029 | } | ||
1030 | } | ||
1031 | if (key_pressed(KEY_DOWN)) { | ||
1032 | if (channel_selection_loc == 3) { | ||
1033 | channel_selection_loc = 0; | ||
1034 | } else { | ||
1035 | channel_selection_loc = CLAMP(channel_selection_loc + 1, 0, 6); | ||
1036 | } | ||
1037 | } | ||
899 | } | 1038 | } |
900 | 1039 | ||
901 | if (key_pressed(KEY_START)) { | 1040 | if (key_pressed(KEY_START)) { |