aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-01-23 10:30:54 +0100
committerBad Diode <bd@badd10de.dev>2024-01-23 10:30:54 +0100
commita7ce765b1b57ec8a528263420852ed36da6d9d84 (patch)
tree99ce3f4b309952bae01ae5ae629c136faefe5774
parentbda8ac3969d40b28c4c14683c1f722647fd17aec (diff)
downloadstepper-a7ce765b1b57ec8a528263420852ed36da6d9d84.tar.gz
stepper-a7ce765b1b57ec8a528263420852ed36da6d9d84.zip
Update profiling macros
-rw-r--r--src/gba/gba.h84
-rw-r--r--src/main.c94
-rw-r--r--src/profiling.c253
-rw-r--r--src/sequencer.c1
-rw-r--r--src/settings.c2
5 files changed, 182 insertions, 252 deletions
diff --git a/src/gba/gba.h b/src/gba/gba.h
index b5868f0..2cc167f 100644
--- a/src/gba/gba.h
+++ b/src/gba/gba.h
@@ -237,25 +237,25 @@ flip_page(vu16 *backbuffer) {
237static inline 237static inline
238void 238void
239profile_start(void) { 239profile_start(void) {
240 TIMER_DATA_2 = 0; 240 TIMER_DATA_1 = 0;
241 TIMER_DATA_3 = 0; 241 TIMER_DATA_0 = 0;
242 TIMER_CTRL_2 = 0; 242 TIMER_CTRL_1 = 0;
243 TIMER_CTRL_3 = 0; 243 TIMER_CTRL_0 = 0;
244 TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE; 244 TIMER_CTRL_1 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE;
245 TIMER_CTRL_2 = TIMER_CTRL_ENABLE; 245 TIMER_CTRL_0 = TIMER_CTRL_ENABLE;
246} 246}
247 247
248static inline 248static inline
249u32 249u32
250profile_stop(void) { 250profile_stop(void) {
251 TIMER_CTRL_2 = 0; 251 TIMER_CTRL_0 = 0;
252 return (TIMER_DATA_3 << 16) | TIMER_DATA_2; 252 return (TIMER_DATA_1 << 16) | TIMER_DATA_0;
253} 253}
254 254
255static inline 255static inline
256u32 256u32
257profile_measure(void) { 257profile_measure(void) {
258 return (TIMER_DATA_3 << 16) | TIMER_DATA_2; 258 return (TIMER_DATA_1 << 16) | TIMER_DATA_0;
259} 259}
260 260
261// 261//
@@ -289,12 +289,24 @@ profile_measure(void) {
289static u16 key_curr = 0; 289static u16 key_curr = 0;
290static u16 key_prev = 0; 290static u16 key_prev = 0;
291 291
292static inline 292// Stores number of frames since a keay was pressed.
293void 293typedef struct Controller {
294poll_keys(void) { 294 int key_up;
295 key_prev = key_curr; 295 int key_down;
296 key_curr = ~KEY_INPUTS & KEY_MASK; 296 int key_left;
297} 297 int key_right;
298 int key_select;
299 int key_start;
300 int key_b;
301 int key_a;
302 int key_l;
303 int key_r;
304} Controller;
305
306static Controller ctrl = {0};
307
308#define RETRIG_OFFSET 16
309#define RETRIG_FRAMES 3
298 310
299// Returns true if the given key has been pressed at time of calling and was not 311// Returns true if the given key has been pressed at time of calling and was not
300// pressed since the previous call. For example, if a key is being held, this 312// pressed since the previous call. For example, if a key is being held, this
@@ -327,25 +339,6 @@ key_hold(u32 key) {
327 return key_curr & key_prev & key; 339 return key_curr & key_prev & key;
328} 340}
329 341
330// Stores number of frames since a keay was pressed.
331typedef struct Controller {
332 int key_up;
333 int key_down;
334 int key_left;
335 int key_right;
336 int key_select;
337 int key_start;
338 int key_b;
339 int key_a;
340 int key_l;
341 int key_r;
342} Controller;
343
344static Controller ctrl = {0};
345
346#define RETRIG_OFFSET 16
347#define RETRIG_FRAMES 3
348
349static inline 342static inline
350bool 343bool
351_key_retrig(int key, int offset, int frames) { 344_key_retrig(int key, int offset, int frames) {
@@ -438,6 +431,14 @@ update_controller(void) {
438 if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; } 431 if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; }
439} 432}
440 433
434static inline
435void
436poll_keys(void) {
437 key_prev = key_curr;
438 key_curr = ~KEY_INPUTS & KEY_MASK;
439 update_controller();
440}
441
441// 442//
442// Direct Memory Access (DMA) 443// Direct Memory Access (DMA)
443// 444//
@@ -785,6 +786,7 @@ wait_vsync(void) {
785// General utility macros. 786// General utility macros.
786#define MIN(A, B) ((A) <= (B) ? (A) : (B)) 787#define MIN(A, B) ((A) <= (B) ? (A) : (B))
787#define MAX(A, B) ((A) >= (B) ? (A) : (B)) 788#define MAX(A, B) ((A) >= (B) ? (A) : (B))
789#define ABS(A) (((A) ^ ((A) >> (sizeof(A) * 8 - 1))) - ((A) >> (sizeof(A) * 8 - 1)))
788#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) 790#define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X))
789#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) 791#define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0]))
790 792
@@ -812,10 +814,24 @@ memcpy32(u32 *dst, const u32 *src, u32 size) {
812 } 814 }
813} 815}
814 816
817static inline
818void
819memset32(u32 *dst, const u32 data, u32 size) {
820 for (size_t i = 0; i < size / 4; i++) {
821 dst[i] = data;
822 }
823}
824
825// Optimized ARMASM versions of memcpy32 and memset32.
826extern void copy32(u32 *dst, u32 *src, u32 chunks);
827extern void set32(u32 *dst, u32 data, u32 chunks);
828
815// 829//
816// Compiler hints. 830// Compiler hints.
817// 831//
818 832
819#define UNROLL_LOOPS __attribute__((optimize("unroll-loops"))) 833#define UNROLL_LOOPS __attribute__((optimize("unroll-loops")))
834#define INLINE __attribute__((always_inline)) inline
820 835
821#endif // GBA_H 836#endif // GBA_H
837
diff --git a/src/main.c b/src/main.c
index a4d3421..6f1d0e6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -11,7 +11,8 @@ WITH REGARD TO THIS SOFTWARE.
11 11
12// TODO: A list of features I would like to get to implement in the near future. 12// TODO: A list of features I would like to get to implement in the near future.
13// 13//
14// High priority: 14// Remaining issues:
15//
15// + Higher resolution clock to allow for microtiming and more accurate tempo. 16// + Higher resolution clock to allow for microtiming and more accurate tempo.
16// + Look back again at the emulator issues... (I give up) 17// + Look back again at the emulator issues... (I give up)
17// + Sync via MIDI with the Analogue cables. 18// + Sync via MIDI with the Analogue cables.
@@ -32,30 +33,18 @@ WITH REGARD TO THIS SOFTWARE.
32// + Fix A+B on ch3 33// + Fix A+B on ch3
33// + Make sure Attack/Decay are grey for A+B 34// + Make sure Attack/Decay are grey for A+B
34// + Add help for attack/decay on ch3 35// + Add help for attack/decay on ch3
36// + Bad performance when selecting patterns?
35// - Fix any bugs we currently have 37// - Fix any bugs we currently have
36// - Add clipboard sharing between banks. 38// - Add clipboard sharing between banks.
37// - Make sure transposing a sequence past the keyboard limit doesn't affect 39// - Make sure transposing a sequence past the keyboard limit doesn't affect
38// the sequence and can be reversed. 40// the sequence and can be reversed.
39// - Study saving overhauls for bootleg cartridges. 41// - Study saving overhauls for bootleg cartridges.
40// - When putting a new trigger, make sure it uses the global parameters 42// - When putting a new trigger, make sure it uses the global parameters
41// - Bad performance when selecting patterns? 43// - Improve memcpy32 performance (ASM?). We use it a lot in expensive places.
42//
43// Low priority:
44//
45// Quality of life improvements.
46// - When not on play mode, adjusting a note or a parameter triggers the sound.
47// This could get annoying, so maybe it should be a configuration option to
48// enable it?
49// - Undo/Redo.
50//
51// Advanced
52// - Add tap tempo for BPM. 44// - Add tap tempo for BPM.
53// - Allow "marking" several trigs to be able to copy/paste them and/or adjust 45// - Improve drawing routines even more (ASM?).
54// their parameters. 46// - Improve interrupt handler to allow nesting/prioritization.
55// - Per trig LFO? How would we go about this? There is at least one empty slot 47//
56// in all channels. LFO amount? LFO speed? Would need a dedicated page for
57// configuring LFOs
58
59 48
60#include "gba/gba.h" 49#include "gba/gba.h"
61 50
@@ -76,37 +65,37 @@ static int frames = 0;
76void 65void
77render_sequencer(void) { 66render_sequencer(void) {
78 if (redraw_trigs) { 67 if (redraw_trigs) {
79 PROF(draw_triggers(), draw_trigs_cycles); 68 draw_triggers();
80 redraw_trigs = false; 69 redraw_trigs = false;
81 } 70 }
82 if (redraw_channels) { 71 if (redraw_channels) {
83 PROF(draw_channels(), draw_btn_cycles); 72 draw_channels();
84 redraw_channels = false; 73 redraw_channels = false;
85 } 74 }
86 if (redraw_pattern_buttons) { 75 if (redraw_pattern_buttons) {
87 PROF(draw_pattern_buttons(), draw_btn_cycles); 76 draw_pattern_buttons();
88 redraw_pattern_buttons = false; 77 redraw_pattern_buttons = false;
89 } 78 }
90 if (redraw_bank_buttons) { 79 if (redraw_bank_buttons) {
91 PROF(draw_bank_buttons(), draw_btn_cycles); 80 draw_bank_buttons();
92 redraw_bank_buttons = false; 81 redraw_bank_buttons = false;
93 } 82 }
94 if (redraw_bpm) { 83 if (redraw_bpm) {
95 PROF(draw_bpm(), draw_btn_cycles); 84 draw_bpm();
96 redraw_bpm = false; 85 redraw_bpm = false;
97 } 86 }
98 if (redraw_play_pause) { 87 if (redraw_play_pause) {
99 PROF(draw_play(), draw_btn_cycles); 88 draw_play();
100 PROF(draw_stop(), draw_btn_cycles); 89 draw_stop();
101 PROF(draw_settings(), draw_btn_cycles); 90 draw_settings();
102 redraw_play_pause = false; 91 redraw_play_pause = false;
103 } 92 }
104 if (redraw_scale) { 93 if (redraw_scale) {
105 PROF(draw_scale(), draw_btn_cycles); 94 draw_scale();
106 redraw_scale = false; 95 redraw_scale = false;
107 } 96 }
108 if (redraw_params) { 97 if (redraw_params) {
109 PROF(draw_parameters(), draw_param_cycles); 98 draw_parameters();
110 redraw_params = false; 99 redraw_params = false;
111 } 100 }
112 101
@@ -117,11 +106,13 @@ render_sequencer(void) {
117 } 106 }
118 } 107 }
119 108
120 if (frames++ & 0x1) { 109 if (frames & 0x1) {
121 draw_notif_bar(); 110 draw_notif_bar();
122 PROF(draw_piano_notes(), draw_piano_cycles);
123 } 111 }
124 PROF(draw_cursors(), draw_cursor_cycles); 112 if (frames++ % 0x4 == 0) {
113 draw_piano_notes();
114 }
115 draw_cursors();
125} 116}
126 117
127void 118void
@@ -169,28 +160,22 @@ render_settings(void) {
169 txt_drawf("HELP", x0 + 2, y0 + 1, COL_FG); 160 txt_drawf("HELP", x0 + 2, y0 + 1, COL_FG);
170 txt_drawf("%s", x1 + 8, y0 + 1, COL_FG, toggle_settings_str[settings.help]); 161 txt_drawf("%s", x1 + 8, y0 + 1, COL_FG, toggle_settings_str[settings.help]);
171 162
172 PROF(draw_settings_cursor(), draw_cursor_cycles); 163 draw_settings_cursor();
173} 164}
174 165
175void 166void
176render(void) { 167render(void) {
177 // NOTE: Debug key input
178 // PROF(screen_fill(COL_BG), clear_cycles);
179 // txt_printf("UP: %d\n", ctrl.key_up);
180 // txt_printf("DOWN: %d\n", ctrl.key_down);
181 // txt_printf("LEFT: %d\n", ctrl.key_left);
182 // txt_printf("RIGHT: %d\n", ctrl.key_right);
183 // txt_printf("A: %d\n", ctrl.key_a);
184 // txt_printf("B: %d\n", ctrl.key_b);
185 // txt_printf("L: %d\n", ctrl.key_l);
186 // txt_printf("R: %d\n", ctrl.key_r);
187 // txt_printf("SEL: %d\n", ctrl.key_select);
188 // txt_printf("START: %d\n", ctrl.key_start);
189 // txt_render();
190 // txt_clear();
191 if (clear_screen) { 168 if (clear_screen) {
192 PROF(screen_fill(COL_BG), clear_cycles); 169 PROF(screen_fill(COL_BG), PROF_FILL);
193 clear_screen = false; 170 clear_screen = false;
171 redraw_trigs = true;
172 redraw_channels = true;
173 redraw_pattern_buttons = true;
174 redraw_bank_buttons = true;
175 redraw_bpm = true;
176 redraw_play_pause = true;
177 redraw_params = true;
178 redraw_scale = true;
194 } 179 }
195 switch (scene) { 180 switch (scene) {
196 case SCENE_SETTINGS: { 181 case SCENE_SETTINGS: {
@@ -206,6 +191,10 @@ render(void) {
206 191
207void 192void
208handle_input(void) { 193handle_input(void) {
194 if (key_tap(KEY_SELECT) && key_hold(KEY_START)) {
195 PROF_SHOW();
196 clear_screen = true;
197 }
209 switch (scene) { 198 switch (scene) {
210 case SCENE_SETTINGS: { 199 case SCENE_SETTINGS: {
211 handle_settings_input(); 200 handle_settings_input();
@@ -218,7 +207,6 @@ handle_input(void) {
218 207
219void 208void
220update(void) { 209update(void) {
221 update_controller();
222 if (next_scene != scene) { 210 if (next_scene != scene) {
223 scene = next_scene; 211 scene = next_scene;
224 clear_screen = true; 212 clear_screen = true;
@@ -269,15 +257,15 @@ main(void) {
269 txt_spacing(6); 257 txt_spacing(6);
270 258
271 // Main loop. 259 // Main loop.
260 PROF_INIT();
272 while (true) { 261 while (true) {
273 poll_keys(); 262 poll_keys();
274 bios_vblank_wait(); 263 bios_vblank_wait();
275 PROF_SHOW();
276 FRAME_START(); 264 FRAME_START();
277 PROF(flip_buffer(), flip_cycles); 265 PROF(flip_buffer(), PROF_FLIP);
278 PROF(update(), update_cycles); 266 PROF(update(), PROF_UPDATE);
279 PROF(handle_input(), input_cycles); 267 PROF(handle_input(), PROF_INPUT);
280 PROF(render(), render_cycles); 268 PROF(render(), PROF_RENDER);
281 FRAME_END(); 269 FRAME_END();
282 } 270 }
283 271
diff --git a/src/profiling.c b/src/profiling.c
index 0255552..6b073ed 100644
--- a/src/profiling.c
+++ b/src/profiling.c
@@ -6,184 +6,111 @@
6#define PROF_ENABLE 0 6#define PROF_ENABLE 0
7#endif 7#endif
8 8
9#if PROF_ENABLE > 0 && PROF_ENABLE < 3 9#if PROF_ENABLE > 0
10 10
11#ifndef PROF_N_FRAMES 11#ifndef PROF_RESET_MINMAX
12#define PROF_N_FRAMES 30 12#define PROF_RESET_MINMAX false
13#endif 13#endif
14 14
15// Profile method 1: Average per N frames. 15// Maximum number of profiling to monitor.
16#if PROF_ENABLE == 1 16typedef enum ProfType {
17#define TEXT_ENABLE 1 17 PROF_INPUT,
18#define PROF(F,VAR) \ 18 PROF_UPDATE,
19 do { \ 19 PROF_RENDER,
20 u32 __tmp_prof = profile_measure();\ 20 PROF_FLIP,
21 F;\ 21 PROF_FILL,
22 (VAR) += profile_measure() - __tmp_prof;\ 22 PROF_NUM,
23 } while (0) 23} ProfType;
24 24
25// Profile method 2: Maximum in N frames. 25char *prof_type_str[PROF_NUM] = {
26#elif PROF_ENABLE == 2 26 "INPUT ",
27#define TEXT_ENABLE 1 27 "UPDATE ",
28#define PROF(F,VAR) \ 28 "RENDER ",
29 do { \ 29 "FLIPBUF",
30 u32 __tmp_prof = profile_measure();\ 30 "SCRFILL",
31 (F);\ 31};
32 (VAR) = MAX(profile_measure() - __tmp_prof, (VAR));\
33 } while (0)
34#endif
35 32
36#ifndef PROF_SHOW_X 33u32 prof_frame_time = 0;
37#define PROF_SHOW_X 0 34u32 prof_frame_count = 0;
38#endif 35u32 prof_frame_avg = -1;
39#ifndef PROF_SHOW_Y 36u32 prof_frame_time_max = 0;
40#define PROF_SHOW_Y 0 37u32 prof_times[PROF_NUM] = {0};
41#endif 38u32 prof_count[PROF_NUM] = {0};
39u32 prof_avg[PROF_NUM] = {0};
40u32 prof_max[PROF_NUM] = {0};
41u32 prof_min[PROF_NUM] = {0};
42 42
43static bool profile_show = true; 43bool prof_reset_minmax = PROF_RESET_MINMAX;
44bool prof_show = true;
44 45
45#define PROF_SHOW() \ 46#define PROF_INIT() do { \
46 do { \ 47 for (size_t i = 0; i < PROF_NUM; i++) { \
47 if (key_tap(KEY_START)) {\ 48 prof_min[i] = -1; \
48 profile_show ^= 1;\ 49 } \
49 }\ 50} while(0);
50 if (profile_show) {\
51 txt_color(1);\
52 txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\
53 draw_filled_rect((PROF_SHOW_X), (PROF_SHOW_X), 8 * 14, 8 * 10, 0);\
54 txt_printf("VIDEO\n");\
55 txt_printf(">CLEAR %.8lu\n", avg_clear_cycles);\
56 txt_printf(">FLIP %.8lu\n", avg_flip_cycles);\
57 txt_printf("SEQUENCER RENDER\n");\
58 txt_printf(">TRIGS %.8lu\n", avg_draw_trigs_cycles);\
59 txt_printf(">BTNS %.8lu\n", avg_draw_btns_cycles);\
60 txt_printf(">PARAM %.8lu\n", avg_draw_param_cycles);\
61 txt_printf(">PIANO %.8lu\n", avg_draw_piano_cycles);\
62 txt_printf(">CURSOR %.8lu\n", avg_draw_cursor_cycles);\
63 txt_printf("UPDATE %.8lu\n", avg_update_cycles);\
64 txt_printf("INPUT %.8lu\n", avg_input_cycles);\
65 txt_printf("RENDER %.8lu\n", avg_render_cycles);\
66 txt_printf("TOTAL %.8lu\n", avg_frame_cycles);\
67 txt_render();\
68 }\
69 u32 frame_time =\
70 FP_DIV(\
71 FP_NUM(avg_frame_cycles + 1, 2),\
72 FP_NUM(2809, 2),\
73 2) * 166;\
74 u32 fps =\
75 FP_DIV(\
76 FP_NUM(280896 * 60, 2),\
77 FP_NUM(avg_frame_cycles + 1, 2),\
78 2);\
79 draw_filled_rect(8 * 18, 0, 239, 16, 0);\
80 txt_drawf("TIME: %.6lu", 8 * 18, 0, 1, frame_time >> 2);\
81 txt_drawf("MAX FPS: %.4lu", 8 * 18, 8, 1, (fps >> 2) + 1);\
82 } while (0)
83 51
84static u32 prof_frame_counter = 0; 52#define PROF(func, idx) do { \
53 u32 time_before = profile_measure(); \
54 (func); \
55 u32 time_after = profile_measure(); \
56 u32 time_current = time_after - time_before; \
57 prof_times[idx] += time_current; \
58 prof_count[idx]++; \
59 prof_max[idx] = MAX(time_current, prof_max[idx]);\
60 prof_min[idx] = MIN(time_current, prof_min[idx]);\
61} while(0);
85 62
86static u32 frame_cycles = 0; 63#define FRAME_START() do { \
87static u32 flip_cycles = 0; 64 profile_start();\
88static u32 clear_cycles = 0; 65} while(0)
89static u32 input_cycles = 0;
90static u32 draw_trigs_cycles = 0;
91static u32 draw_btn_cycles = 0;
92static u32 draw_piano_cycles = 0;
93static u32 draw_param_cycles = 0;
94static u32 draw_cursor_cycles = 0;
95static u32 render_cycles = 0;
96static u32 update_cycles = 0;
97 66
98static u32 avg_frame_cycles = 0; 67#define FRAME_END() do { \
99static u32 avg_flip_cycles = 0; 68 prof_frame_count++;\
100static u32 avg_clear_cycles = 0; 69 prof_frame_time_max = MAX(prof_frame_time_max, profile_measure());\
101static u32 avg_input_cycles = 0; 70 prof_frame_time += profile_stop();\
102static u32 avg_draw_trigs_cycles = 0; 71 if (prof_show) { \
103static u32 avg_draw_btns_cycles = 0; 72 draw_filled_rect(0, 0, SCREEN_WIDTH - 1, 8 * (PROF_NUM + 1), 0); \
104static u32 avg_draw_piano_cycles = 0; 73 txt_drawf_small("FRAME TIME/FPS: %.9l/%.2l", 0, 0, COL_FG, \
105static u32 avg_draw_param_cycles = 0; 74 prof_frame_avg, \
106static u32 avg_draw_cursor_cycles = 0; 75 (u32)((u64)280896 * 60 / (prof_frame_avg + 1)));\
107static u32 avg_render_cycles = 0; 76 txt_drawf_small("MAX: %.9l/%l", 8 * 19, 0, COL_FG, \
108static u32 avg_update_cycles = 0; 77 prof_frame_time_max,280896);\
78 for (size_t idx = 0; idx < PROF_NUM; idx++) { \
79 txt_drawf_small("%s %.9l (%.9l %.9l) %08x:%08x", 0, 8 * (idx + 1), COL_FG, \
80 prof_type_str[idx], \
81 prof_avg[idx], \
82 prof_min[idx], \
83 prof_max[idx], \
84 prof_avg[idx], \
85 prof_max[idx]);\
86 }; \
87 } \
88 if (prof_frame_count >= PROF_ENABLE) { \
89 for (size_t idx = 0; idx < PROF_NUM; idx++) { \
90 prof_avg[idx] = prof_times[idx] / prof_frame_count; \
91 if (prof_reset_minmax) { \
92 prof_min[idx] = -1; \
93 prof_max[idx] = 0; \
94 } \
95 prof_times[idx] = 0; \
96 prof_count[idx] = 0; \
97 }; \
98 prof_frame_avg = prof_frame_time / prof_frame_count; \
99 prof_frame_count = 0; \
100 prof_frame_time = 0; \
101 } \
102 } while(0)
109 103
110#if PROF_ENABLE == 1 104#define PROF_SHOW() do { \
111#define FRAME_START()\ 105 prof_show ^= 1; \
112 do { \ 106} while(0)
113 if (prof_frame_counter == PROF_N_FRAMES) {\
114 avg_frame_cycles = frame_cycles / prof_frame_counter;\
115 avg_flip_cycles = flip_cycles / prof_frame_counter;\
116 avg_clear_cycles = clear_cycles / prof_frame_counter;\
117 avg_draw_trigs_cycles = draw_trigs_cycles / prof_frame_counter;\
118 avg_draw_btns_cycles = draw_btn_cycles / prof_frame_counter;\
119 avg_draw_piano_cycles = draw_piano_cycles / prof_frame_counter;\
120 avg_draw_param_cycles = draw_param_cycles / prof_frame_counter;\
121 avg_draw_cursor_cycles = draw_cursor_cycles / prof_frame_counter;\
122 avg_input_cycles = input_cycles / prof_frame_counter;\
123 avg_render_cycles = render_cycles / prof_frame_counter;\
124 avg_update_cycles = update_cycles / prof_frame_counter;\
125 frame_cycles = 0;\
126 flip_cycles = 0;\
127 clear_cycles = 0;\
128 input_cycles = 0;\
129 render_cycles = 0;\
130 update_cycles = 0;\
131 draw_trigs_cycles = 0;\
132 draw_param_cycles = 0;\
133 draw_cursor_cycles = 0;\
134 draw_btn_cycles = 0;\
135 draw_piano_cycles = 0;\
136 prof_frame_counter = 0;\
137 }\
138 profile_start();\
139 } while (0)
140#elif PROF_ENABLE == 2
141#define FRAME_START()\
142 do { \
143 if (prof_frame_counter == PROF_N_FRAMES) {\
144 avg_frame_cycles = frame_cycles;\
145 avg_flip_cycles = flip_cycles;\
146 avg_clear_cycles = clear_cycles;\
147 avg_line_cycles = line_cycles;\
148 avg_rect_cycles = rect_cycles;\
149 avg_fill_rect_cycles = fill_rect_cycles;\
150 avg_chr_cycles = chr_cycles;\
151 avg_icn_cycles = icn_cycles;\
152 avg_txt_drawf_cycles = txt_drawf_cycles;\
153 avg_txt_printf_cycles = txt_printf_cycles;\
154 avg_txt_render_cycles = txt_render_cycles;\
155 avg_txt_clear_cycles = txt_clear_cycles;\
156 avg_input_cycles = input_cycles;\
157 frame_cycles = 0;\
158 flip_cycles = 0;\
159 clear_cycles = 0;\
160 line_cycles = 0;\
161 rect_cycles = 0;\
162 fill_rect_cycles = 0;\
163 chr_cycles = 0;\
164 icn_cycles = 0;\
165 txt_drawf_cycles = 0;\
166 txt_printf_cycles = 0;\
167 txt_render_cycles = 0;\
168 txt_clear_cycles = 0;\
169 input_cycles = 0;\
170 prof_frame_counter = 0;\
171 }\
172 profile_start();\
173 } while (0)
174#endif
175
176#define FRAME_END() \
177 do { \
178 prof_frame_counter++;\
179 frame_cycles += profile_stop();\
180 } while (0)
181 107
182#else 108#else
183 109
184// No profiling. 110// No profiling.
185#define PROF(F,VAR) (F) 111#define PROF_INIT()
186#define PROF_SHOW() 112#define PROF(F,VAR) do {F;} while(0)
187#define FRAME_START() 113#define FRAME_START()
188#define FRAME_END() 114#define FRAME_END()
115#define PROF_SHOW()
189#endif 116#endif
diff --git a/src/sequencer.c b/src/sequencer.c
index c01f905..4f46e1f 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -351,7 +351,6 @@ IWRAM_CODE
351UNROLL_LOOPS 351UNROLL_LOOPS
352void 352void
353wave_ad_tick(void) { 353wave_ad_tick(void) {
354 Wave wave_active = {0};
355 Wave wave_zero = { 354 Wave wave_zero = {
356 0x77777777, 0x77777777, 0x77777777, 0x77777777, 355 0x77777777, 0x77777777, 0x77777777, 0x77777777,
357 }; 356 };
diff --git a/src/settings.c b/src/settings.c
index 9fc2f3d..3e8138e 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -31,7 +31,7 @@ set_audio_settings(void) {
31 case SYNC_IN_LINK_4BPQ: { irs_set(IRQ_SERIAL, sync_in_4); } break; 31 case SYNC_IN_LINK_4BPQ: { irs_set(IRQ_SERIAL, sync_in_4); } break;
32 default: break; 32 default: break;
33 } 33 }
34 irs_set(IRQ_TIMER_2, NULL); 34 irs_set(IRQ_TIMER_3, NULL);
35 SIO_MODE = SIO_MODE_GP 35 SIO_MODE = SIO_MODE_GP
36 | SIO_SC_OUT(0) 36 | SIO_SC_OUT(0)
37 | SIO_SD_OUT(0) 37 | SIO_SD_OUT(0)