diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/drawing.c | 75 | ||||
-rw-r--r-- | src/globals.c | 11 | ||||
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/sequencer.c | 91 |
4 files changed, 156 insertions, 41 deletions
diff --git a/src/drawing.c b/src/drawing.c index 50f3de3..e94d0ff 100644 --- a/src/drawing.c +++ b/src/drawing.c | |||
@@ -594,9 +594,19 @@ draw_piano(void) { | |||
594 | draw_rect(x0, y0, x1, y1, COL_FG); | 594 | draw_rect(x0, y0, x1, y1, COL_FG); |
595 | for (size_t i = 0; i < 12 * 6; i++) { | 595 | for (size_t i = 0; i < 12 * 6; i++) { |
596 | u8 clr = COL_FG; | 596 | u8 clr = COL_FG; |
597 | s8 pos = i % 12; | ||
598 | switch (pos) { | ||
599 | case 0: | ||
600 | case 2: | ||
601 | case 4: | ||
602 | case 5: | ||
603 | case 7: | ||
604 | case 9: | ||
605 | case 11: break; | ||
606 | default: { clr = COL_BG; } break; | ||
607 | } | ||
597 | if (input_handler == handle_right_col_selection && | 608 | if (input_handler == handle_right_col_selection && |
598 | right_col_selection_loc == R_COL_SCALE) { | 609 | right_col_selection_loc == R_COL_SCALE) { |
599 | s8 pos = i % 12; | ||
600 | if (pos == current_scale_root) { | 610 | if (pos == current_scale_root) { |
601 | clr = COL_ACC_1; | 611 | clr = COL_ACC_1; |
602 | } else { | 612 | } else { |
@@ -1277,13 +1287,38 @@ clear_cursors(void) { | |||
1277 | 1287 | ||
1278 | void | 1288 | void |
1279 | draw_pattern_chain_cursor(void) { | 1289 | draw_pattern_chain_cursor(void) { |
1280 | size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8); | 1290 | switch (param_selection_loc) { |
1281 | size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y; | 1291 | case CHAIN_BTN_ENABLE: { |
1282 | size_t x0 = PAT_TRIG_START_X + offset_x; | 1292 | size_t x0 = PAT_TRIG_START_X + 24; |
1283 | size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; | 1293 | size_t x1 = x0 + 30; |
1284 | size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2; | 1294 | size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; |
1285 | draw_line(x0, y, x1, y, COL_ACC_0); | 1295 | draw_line(x0, y, x1, y, COL_ACC_0); |
1286 | draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); | 1296 | draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); |
1297 | } break; | ||
1298 | case CHAIN_BTN_CLEAR: { | ||
1299 | size_t x0 = PAT_TRIG_START_X + 24 + 42; | ||
1300 | size_t x1 = x0 + 30; | ||
1301 | size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; | ||
1302 | draw_line(x0, y, x1, y, COL_ACC_0); | ||
1303 | draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); | ||
1304 | } break; | ||
1305 | case CHAIN_BTN_RANDOM: { | ||
1306 | size_t x0 = PAT_TRIG_START_X + 24 + 42 * 2; | ||
1307 | size_t x1 = x0 + 30; | ||
1308 | size_t y = PAT_TRIG_START_Y - 16 + 1 + 10; | ||
1309 | draw_line(x0, y, x1, y, COL_ACC_0); | ||
1310 | draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); | ||
1311 | } break; | ||
1312 | default: { | ||
1313 | size_t offset_x = (PAT_TRIG_H + 7) * (param_selection_loc % 8); | ||
1314 | size_t offset_y = param_selection_loc < 8 ? 0 : 0 + PAT_TRIG_OFFSET_Y; | ||
1315 | size_t x0 = PAT_TRIG_START_X + offset_x; | ||
1316 | size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; | ||
1317 | size_t y = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H + 2; | ||
1318 | draw_line(x0, y, x1, y, COL_ACC_0); | ||
1319 | draw_line(x0, y + 1, x1, y + 1, COL_ACC_0); | ||
1320 | } break; | ||
1321 | } | ||
1287 | } | 1322 | } |
1288 | 1323 | ||
1289 | void | 1324 | void |
@@ -1756,7 +1791,7 @@ draw_notif_bar() { | |||
1756 | return; | 1791 | return; |
1757 | } | 1792 | } |
1758 | 1793 | ||
1759 | if (chain.len != 0) { | 1794 | if (chain.len != 0 && chain.enabled) { |
1760 | u8 x = x0 + 2; | 1795 | u8 x = x0 + 2; |
1761 | u8 y = y0 + 1; | 1796 | u8 y = y0 + 1; |
1762 | txt_drawf_small("CHAIN: ", x, y, color); | 1797 | txt_drawf_small("CHAIN: ", x, y, color); |
@@ -1789,6 +1824,7 @@ draw_notif_bar() { | |||
1789 | void | 1824 | void |
1790 | draw_pattern_chain() { | 1825 | draw_pattern_chain() { |
1791 | clear_parameters(); | 1826 | clear_parameters(); |
1827 | // Pattern chain triggers. | ||
1792 | for (size_t i = 0; i < 16; i++) { | 1828 | for (size_t i = 0; i < 16; i++) { |
1793 | u8 color = COL_FG; | 1829 | u8 color = COL_FG; |
1794 | size_t offset_x = PAT_TRIG_OFFSET_X * (i % 8); | 1830 | size_t offset_x = PAT_TRIG_OFFSET_X * (i % 8); |
@@ -1797,12 +1833,15 @@ draw_pattern_chain() { | |||
1797 | size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; | 1833 | size_t x1 = PAT_TRIG_START_X + offset_x + PAT_TRIG_W; |
1798 | size_t y0 = PAT_TRIG_START_Y + offset_y; | 1834 | size_t y0 = PAT_TRIG_START_Y + offset_y; |
1799 | size_t y1 = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H; | 1835 | size_t y1 = PAT_TRIG_START_Y + offset_y + PAT_TRIG_H; |
1836 | if (!chain.enabled) { | ||
1837 | color = COL_OFF; | ||
1838 | } | ||
1800 | draw_rect(x0, y0, x1, y1, color); | 1839 | draw_rect(x0, y0, x1, y1, color); |
1801 | if (chain.active[i]) { | 1840 | if (chain.active[i]) { |
1802 | txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); | 1841 | txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); |
1803 | } | 1842 | } |
1804 | color = COL_OFF; | 1843 | color = COL_OFF; |
1805 | if (chain.current == i && chain.len != 0) { | 1844 | if (chain.current == i && chain.len != 0 && chain.enabled) { |
1806 | color = COL_ACC_2; | 1845 | color = COL_ACC_2; |
1807 | if (chain.active[i]) { | 1846 | if (chain.active[i]) { |
1808 | txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); | 1847 | txt_drawc('A' + chain.chain[i], x0 + 4, y0 + 3, color); |
@@ -1811,4 +1850,20 @@ draw_pattern_chain() { | |||
1811 | } | 1850 | } |
1812 | draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, color); | 1851 | draw_line(x0 + 5, y1 - 2, x1 - 5, y1 - 2, color); |
1813 | } | 1852 | } |
1853 | |||
1854 | // Pattern chain buttons. | ||
1855 | size_t x0 = PAT_TRIG_START_X + 24; | ||
1856 | size_t x1 = x0 + 30; | ||
1857 | size_t y0 = PAT_TRIG_START_Y - 16 + 1; | ||
1858 | size_t y1 = y0 + 8; | ||
1859 | txt_drawf_small("toggle", x0 + 2, y0, COL_FG); | ||
1860 | draw_rect(x0, y0, x1, y1, COL_FG); | ||
1861 | x0 += 42; | ||
1862 | x1 += 42; | ||
1863 | txt_drawf_small("clear", x0 + 4, y0, COL_FG); | ||
1864 | draw_rect(x0, y0, x1, y1, COL_FG); | ||
1865 | x0 += 42; | ||
1866 | x1 += 42; | ||
1867 | txt_drawf_small("random", x0 + 2, y0, COL_FG); | ||
1868 | draw_rect(x0, y0, x1, y1, COL_FG); | ||
1814 | } | 1869 | } |
diff --git a/src/globals.c b/src/globals.c index 7361129..05c964a 100644 --- a/src/globals.c +++ b/src/globals.c | |||
@@ -57,7 +57,7 @@ bool clear_screen = true; | |||
57 | #define NOTIF_START_Y 12 | 57 | #define NOTIF_START_Y 12 |
58 | 58 | ||
59 | #define PARAMS_W 166 | 59 | #define PARAMS_W 166 |
60 | #define PARAMS_H 52 | 60 | #define PARAMS_H 56 |
61 | #define PARAMS_START_X 29 | 61 | #define PARAMS_START_X 29 |
62 | #define PARAMS_START_Y 20 | 62 | #define PARAMS_START_Y 20 |
63 | #define PARAMS_BOX_W 30 | 63 | #define PARAMS_BOX_W 30 |
@@ -99,7 +99,7 @@ bool clear_screen = true; | |||
99 | #define PAT_TRIG_W 14 | 99 | #define PAT_TRIG_W 14 |
100 | #define PAT_TRIG_H 14 | 100 | #define PAT_TRIG_H 14 |
101 | #define PAT_TRIG_START_X 32 | 101 | #define PAT_TRIG_START_X 32 |
102 | #define PAT_TRIG_START_Y 30 | 102 | #define PAT_TRIG_START_Y 37 |
103 | #define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7) | 103 | #define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7) |
104 | #define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8) | 104 | #define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8) |
105 | 105 | ||
@@ -167,8 +167,15 @@ typedef struct Chain { | |||
167 | u8 len; | 167 | u8 len; |
168 | u8 current; | 168 | u8 current; |
169 | u8 playing; | 169 | u8 playing; |
170 | u8 enabled; | ||
170 | } Chain; | 171 | } Chain; |
171 | 172 | ||
173 | typedef enum ChainButtons { | ||
174 | CHAIN_BTN_ENABLE = 16, | ||
175 | CHAIN_BTN_CLEAR = 17, | ||
176 | CHAIN_BTN_RANDOM = 18, | ||
177 | } ChainButtons; | ||
178 | |||
172 | static Chain chain = {0}; | 179 | static Chain chain = {0}; |
173 | 180 | ||
174 | typedef enum Prob { | 181 | typedef enum Prob { |
@@ -37,6 +37,8 @@ WITH REGARD TO THIS SOFTWARE. | |||
37 | // - Channel params should show if there are some already on all triggers and | 37 | // - Channel params should show if there are some already on all triggers and |
38 | // modify only the selected parameter, not all of them. | 38 | // modify only the selected parameter, not all of them. |
39 | // - Should scale mode be toggleable? | 39 | // - Should scale mode be toggleable? |
40 | // - Improve SRAM saving to make room for longer patterns and/or more banks. | ||
41 | // - Higher resolution clock to allow for microtiming and more accurate tempo. | ||
40 | // | 42 | // |
41 | // WIP (1.7) | 43 | // WIP (1.7) |
42 | // + Improve "grey" cursor with dithering instead. | 44 | // + Improve "grey" cursor with dithering instead. |
@@ -55,18 +57,18 @@ WITH REGARD TO THIS SOFTWARE. | |||
55 | // + Make sure bank switching is queued like patterns. | 57 | // + Make sure bank switching is queued like patterns. |
56 | // + If we are on sync in, BPM should display SYNC | 58 | // + If we are on sync in, BPM should display SYNC |
57 | // + Visual feedback for scale/root note adjustment. | 59 | // + Visual feedback for scale/root note adjustment. |
58 | // - Shortcut to quickly exit/enter chain mode. | 60 | // + Settings page overhaul. |
61 | // + Add global mutes option. | ||
62 | // + Add global bpm option. | ||
63 | // + Add auto-save option. | ||
64 | // + Remove thin cursor option and make the fat one default, it's just better. | ||
65 | // + Restore black keys when not on scale mode | ||
66 | // + Enable pattern chain toggling. | ||
67 | // + Enable pattern chain clearing. | ||
68 | // + Enable pattern chain randomizing. | ||
59 | // - Add CREDITS to the documentation for now, should probably be a menu item | 69 | // - Add CREDITS to the documentation for now, should probably be a menu item |
60 | // later. | 70 | // later. |
61 | // - Settings page overhaul. | ||
62 | // - Remove thin cursor option and make the fat one default, it's just better. | ||
63 | // | ||
64 | // - Improve SRAM saving to make room for longer patterns and/or more banks. | ||
65 | // - Higher resolution clock to allow for microtiming and more accurate tempo. | ||
66 | // - Add settings for "performance mode" in which banks are not saved by | ||
67 | // default while changing patterns. | ||
68 | // - Make sure sync works with the same cable for in/out. | 71 | // - Make sure sync works with the same cable for in/out. |
69 | // - Study more improvements for a "performance mode". | ||
70 | 72 | ||
71 | #include "gba/gba.h" | 73 | #include "gba/gba.h" |
72 | 74 | ||
diff --git a/src/sequencer.c b/src/sequencer.c index 58714cb..266db94 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -138,7 +138,7 @@ play_step(void) { | |||
138 | } else if (current_bank != next_bank && step_counter == 15) { | 138 | } else if (current_bank != next_bank && step_counter == 15) { |
139 | select_bank(next_bank); | 139 | select_bank(next_bank); |
140 | update_bpm = true; | 140 | update_bpm = true; |
141 | } else if (chain.len != 0 && step_counter == 15) { | 141 | } else if (chain.len != 0 && step_counter == 15 && chain.enabled) { |
142 | redraw_pattern_buttons = true; | 142 | redraw_pattern_buttons = true; |
143 | update_bpm = true; | 143 | update_bpm = true; |
144 | if (!chain.playing) { | 144 | if (!chain.playing) { |
@@ -762,6 +762,8 @@ handle_pattern_chain(void) { | |||
762 | } else if (key_tap(KEY_LEFT)) { | 762 | } else if (key_tap(KEY_LEFT)) { |
763 | if (param_selection_loc == 8) { | 763 | if (param_selection_loc == 8) { |
764 | param_selection_loc = 15; | 764 | param_selection_loc = 15; |
765 | } else if (param_selection_loc == 16) { | ||
766 | param_selection_loc = 18; | ||
765 | } else if (param_selection_loc > 0) { | 767 | } else if (param_selection_loc > 0) { |
766 | param_selection_loc--; | 768 | param_selection_loc--; |
767 | } else if (param_selection_loc == 0) { | 769 | } else if (param_selection_loc == 0) { |
@@ -770,48 +772,97 @@ handle_pattern_chain(void) { | |||
770 | } else if (key_tap(KEY_RIGHT)) { | 772 | } else if (key_tap(KEY_RIGHT)) { |
771 | if (param_selection_loc < 15 && param_selection_loc != 7) { | 773 | if (param_selection_loc < 15 && param_selection_loc != 7) { |
772 | param_selection_loc++; | 774 | param_selection_loc++; |
775 | } else if (param_selection_loc < 18 && param_selection_loc >= 16) { | ||
776 | param_selection_loc++; | ||
777 | } else if (param_selection_loc == 18) { | ||
778 | param_selection_loc = 16; | ||
773 | } else if (param_selection_loc == 7) { | 779 | } else if (param_selection_loc == 7) { |
774 | param_selection_loc = 0; | 780 | param_selection_loc = 0; |
775 | } else if (param_selection_loc == 15) { | 781 | } else if (param_selection_loc == 15) { |
776 | param_selection_loc = 8; | 782 | param_selection_loc = 8; |
777 | } | 783 | } |
778 | } else if (key_tap(KEY_UP)) { | 784 | } else if (key_tap(KEY_UP)) { |
779 | if (param_selection_loc <= 7) { | 785 | if (param_selection_loc >= 1 && param_selection_loc <= 2) { |
780 | param_selection_loc += 8; | 786 | param_selection_loc = 16; |
781 | } else { | 787 | } else if (param_selection_loc >= 3 && param_selection_loc <= 4) { |
788 | param_selection_loc = 17; | ||
789 | } else if (param_selection_loc >= 5 && param_selection_loc <= 6) { | ||
790 | param_selection_loc = 18; | ||
791 | } else if (param_selection_loc >= 8 && param_selection_loc <= 15){ | ||
782 | param_selection_loc -= 8; | 792 | param_selection_loc -= 8; |
783 | } | 793 | } |
784 | } else if (key_tap(KEY_DOWN)) { | 794 | } else if (key_tap(KEY_DOWN)) { |
785 | if (param_selection_loc <= 7) { | 795 | if (param_selection_loc <= 7) { |
786 | param_selection_loc += 8; | 796 | param_selection_loc += 8; |
787 | } else { | 797 | } else if (param_selection_loc == 16){ |
788 | param_selection_loc -= 8; | 798 | param_selection_loc = 1; |
799 | } else if (param_selection_loc == 17){ | ||
800 | param_selection_loc = 3; | ||
801 | } else if (param_selection_loc == 18){ | ||
802 | param_selection_loc = 5; | ||
789 | } | 803 | } |
790 | } else if (key_tap(KEY_B)) { | 804 | } else if (key_tap(KEY_B)) { |
791 | if (chain.active[param_selection_loc]) { | 805 | switch (param_selection_loc) { |
792 | // Can't toggle current chain. | 806 | case CHAIN_BTN_ENABLE: { |
793 | if (!play_status | 807 | chain.enabled ^= 1; |
794 | || param_selection_loc != chain.current | 808 | chain.current = 15; |
795 | || chain.len == 1) { | 809 | chain.current = find_next_pattern(); |
796 | chain.active[param_selection_loc] = 0; | 810 | chain.playing = false; |
797 | chain.len--; | 811 | } break; |
798 | } | 812 | case CHAIN_BTN_CLEAR: { |
799 | } else { | 813 | chain.len = 0; |
800 | if (chain.len == 0) { | 814 | chain.playing = false; |
801 | chain.current = param_selection_loc; | 815 | for (size_t i = 0; i < MAX_CHAIN; i++) { |
802 | } | 816 | chain.active[i] = false; |
803 | chain.active[param_selection_loc] = 1; | 817 | chain.chain[i] = 0; |
804 | chain.len++; | 818 | } |
819 | chain.current = 15; | ||
820 | chain.current = find_next_pattern(); | ||
821 | } break; | ||
822 | case CHAIN_BTN_RANDOM: { | ||
823 | u8 cur = chain.current % 16; | ||
824 | for (size_t i = 0; i < MAX_CHAIN; i++) { | ||
825 | if (i == cur && chain.playing) { | ||
826 | continue; | ||
827 | } | ||
828 | if (rng16() < 32765) { | ||
829 | chain.active[i] = true; | ||
830 | } else { | ||
831 | chain.active[i] = false; | ||
832 | } | ||
833 | // NOTE: Should we also randomize the patterns or isn't it | ||
834 | // necessary? | ||
835 | } | ||
836 | } break; | ||
837 | default: { | ||
838 | if (chain.active[param_selection_loc]) { | ||
839 | // Can't toggle current chain. | ||
840 | if (!play_status | ||
841 | || param_selection_loc != chain.current | ||
842 | || chain.len == 1) { | ||
843 | chain.active[param_selection_loc] = 0; | ||
844 | chain.len--; | ||
845 | } | ||
846 | } else { | ||
847 | if (chain.len == 0) { | ||
848 | chain.current = param_selection_loc; | ||
849 | } | ||
850 | chain.active[param_selection_loc] = 1; | ||
851 | chain.len++; | ||
852 | } | ||
853 | } break; | ||
805 | } | 854 | } |
806 | } else if (key_tap(KEY_L)) { | 855 | } else if (key_tap(KEY_L)) { |
807 | if (chain.active[param_selection_loc] | 856 | if (chain.active[param_selection_loc] |
808 | && chain.chain[param_selection_loc] > 0 | 857 | && chain.chain[param_selection_loc] > 0 |
858 | && param_selection_loc <= 15 | ||
809 | && (!play_status || param_selection_loc != chain.current)) { | 859 | && (!play_status || param_selection_loc != chain.current)) { |
810 | chain.chain[param_selection_loc]--; | 860 | chain.chain[param_selection_loc]--; |
811 | } | 861 | } |
812 | } else if (key_tap(KEY_R)) { | 862 | } else if (key_tap(KEY_R)) { |
813 | if (chain.active[param_selection_loc] | 863 | if (chain.active[param_selection_loc] |
814 | && chain.chain[param_selection_loc] < 7 | 864 | && chain.chain[param_selection_loc] < 7 |
865 | && param_selection_loc <= 15 | ||
815 | && (!play_status || param_selection_loc != chain.current)) { | 866 | && (!play_status || param_selection_loc != chain.current)) { |
816 | chain.chain[param_selection_loc]++; | 867 | chain.chain[param_selection_loc]++; |
817 | } | 868 | } |