summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-02 17:06:03 +0200
committerBad Diode <bd@badd10de.dev>2021-05-02 17:06:03 +0200
commit53c1e688f2b2f559a2bde556c9762519efa66f03 (patch)
treebc5c58c3953594c103e1da1118e8a9899b51e8f6
parent685cc9d6bfb1c376f1231ce7c271c6ab6900b3d9 (diff)
downloadgba-experiments-53c1e688f2b2f559a2bde556c9762519efa66f03.tar.gz
gba-experiments-53c1e688f2b2f559a2bde556c9762519efa66f03.zip
Add sprites for envelope volume control
-rw-r--r--src/sequencer.c198
1 files 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[] = {
99 0x04040407, 0x00000000, 0x00000000, 0x00000000, 99 0x04040407, 0x00000000, 0x00000000, 0x00000000,
100}; 100};
101 101
102u32 sprite_env_labels[] = {
103 // Volume.
104 0xa0a0a0a0, 0xc0000000, 0x262a2a2a, 0xee000000,
105 0xaaeaaaaa, 0xae000000, 0x0e020602, 0x0e000000,
106};
107
108u32 sprite_env_volume[] = {
109 0x80808080, 0x80808000, 0x0f0c0c0c, 0x0c6c6f00,
110 0x1f999919, 0x19999f00, 0x00090d06, 0x030d0c00,
111 0x80808080, 0x80808000, 0x0f01010f, 0x09696f00,
112 0x1f83831f, 0x13939f00, 0x00090d06, 0x030d0c00,
113 0x60606060, 0x60606000, 0x1f18181e, 0x18d8df00,
114 0x3e30303c, 0x30303e00, 0x00131b0c, 0x061b1900,
115 0xf8c0c0f8, 0x1818f800, 0x3e06063e, 0x26a6be00,
116 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200,
117 0xf8c0c0f8, 0x1818f800, 0x3e323232, 0x32b2be00,
118 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200,
119 0xf8c0c0f0, 0xc0c0f800, 0x3e30303c, 0x30b0be00,
120 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200,
121 0xc0e0d0c8, 0xf8c0c000, 0x3e323232, 0x32b2be00,
122 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200,
123 0xc0e0d0c8, 0xf8c0c000, 0x3e06063e, 0x26a6be00,
124 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200,
125 0xf81818f8, 0xc0c0f800, 0x3e30303c, 0x30b0be00,
126 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200,
127 0xf81818f8, 0x9898f800, 0x3e323232, 0x32b2be00,
128 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200,
129 0xf81818f8, 0x9898f800, 0x3e06063e, 0x26a6be00,
130 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200,
131 0xf8c0c060, 0x30181800, 0x3e30303c, 0x30b0be00,
132 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200,
133 0xf8c8c8f8, 0xc8c8f800, 0x3e323232, 0x32b2be00,
134 0x7c646464, 0x64657d00, 0x00263618, 0x0c363200,
135 0xf8c8c8f8, 0xc8c8f800, 0x3e06063e, 0x26a6be00,
136 0x7c0c0c7c, 0x4c4d7d00, 0x00263618, 0x0c363200,
137 0xf8c8c8f8, 0xc0c0f800, 0x3e30303c, 0x30b0be00,
138 0x7c606078, 0x60617d00, 0x00263618, 0x0c363200,
139 0xec2c2c2c, 0x2c2cec00, 0xfbcbcbcb, 0xcbcbfb00,
140 0xf0909090, 0x9096f600, 0x0199d961, 0x31d9c900,
141};
142
102typedef struct SeqTrigger { 143typedef struct SeqTrigger {
103 bool trigger; 144 bool trigger;
104 Note note; 145 Note note;
146 u8 env_volume;
105 // TODO: ... 147 // TODO: ...
106} SeqTrigger; 148} SeqTrigger;
107 149
108static SeqTrigger sequence_synth[] = { 150static SeqTrigger sequence_synth[] = {
109 {true, NOTE_D_4}, 151 {true, NOTE_D_4, 0},
110 {true, NOTE_F_4}, 152 {true, NOTE_F_4, 1},
111 {true, NOTE_A_4}, 153 {true, NOTE_A_4, 2},
112 {true, NOTE_C_5}, 154 {true, NOTE_C_5, 3},
113 155
114 {true, NOTE_D_4}, 156 {true, NOTE_D_4, 4},
115 {false, NOTE_C_SHARP_4}, 157 {false, NOTE_C_SHARP_4, 5},
116 {false, NOTE_D_4}, 158 {false, NOTE_D_4, 6},
117 {false, NOTE_D_4}, 159 {false, NOTE_D_4, 7},
118 160
119 {true, NOTE_D_4}, 161 {true, NOTE_D_4, 8},
120 {true, NOTE_F_4}, 162 {true, NOTE_F_4, 9},
121 {true, NOTE_A_4}, 163 {true, NOTE_A_4, 10},
122 {true, NOTE_C_5}, 164 {true, NOTE_C_5, 11},
123 165
124 {true, NOTE_D_4}, 166 {true, NOTE_D_4, 12},
125 {false, NOTE_D_4}, 167 {false, NOTE_D_4, 13},
126 {true, NOTE_A_4}, 168 {true, NOTE_A_4, 14},
127 {false, NOTE_A_5}, 169 {false, NOTE_A_5, 15},
128}; 170};
129 171
130static int bpm = 120; 172static int bpm = 120;
@@ -133,9 +175,12 @@ static Note active_note;
133 175
134void 176void
135irq_timer_0(void) { 177irq_timer_0(void) {
136 active_note = sequence_synth[step_counter].note; 178 SeqTrigger *trig = &sequence_synth[step_counter];
137 if (sequence_synth[step_counter].trigger) { 179 active_note = trig->note;
138 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(13) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_DUTY(2); 180 if (trig->trigger) {
181 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(trig->env_volume)
182 | SOUND_SQUARE_ENV_TIME(4)
183 | SOUND_SQUARE_DUTY(2);
139 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note]; 184 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note];
140 } 185 }
141 step_counter = (step_counter + 1) % 16; 186 step_counter = (step_counter + 1) % 16;
@@ -161,46 +206,56 @@ set_time(int bpm) {
161// 206//
162// Currently we load all sequencer sprite memory in the VRAM: 207// Currently we load all sequencer sprite memory in the VRAM:
163// 208//
164// - Note names: 73x2 tiles 209// - Note names: 73x2 tiles.
165// - Sprite trigger button: 8 tiles 210// - Sprite trigger button: 8 tiles.
166// - Duration indicator (TODO) 211// - Current step marker: 1 tile.
167// - Current step marker. 212// - Selected trigger marker: 16 tile.
213// - Env: Volume label: 4 tiles.
214// - Env: Volume text: 7x4 tiles
215// - (TODO) Duration indicator
168// 216//
169// The order of OBJs correspond to: 217// The order of OBJs correspond to:
170// 218//
171// - 000-015 step note names. 219// - 000-015 step note names.
172// - 015-029 step trigger steps. 220// - 015-031 step trigger steps.
173// - 030-045 step duration indicators. 221// - 032-032 current step marker.
174// - 046-046 current step marker. 222// - 033-033 trigger selection indicator.
175// - 047-047 trigger selection indicator. 223// - 034-034 envelope: volume label.
224// - 035-0xx envelope: volume indicator.
176// 225//
177 226
227
228// Positioning parameters.
229#define SEQ_TRIG_POS_X 45
230#define SEQ_TRIG_POS_Y 50
231#define SEQ_TRIG_DIST 20
232#define SEQ_ENV_POS_X 10
233#define SEQ_ENV_POS_Y 10
234
178size_t obj_counter = 0; 235size_t obj_counter = 0;
179 236
180typedef struct SeqSprite { 237typedef struct SeqSprite {
181 u8 id; 238 u8 id;
182 int x; 239 int x;
183 int y; 240 int y;
241 size_t base_tile;
184 u16 obj_attr_0; 242 u16 obj_attr_0;
185 u16 obj_attr_1; 243 u16 obj_attr_1;
186 u16 obj_attr_2; 244 u16 obj_attr_2;
187} SeqSprite; 245} SeqSprite;
188 246
189#define SEQ_POS_X 45
190#define SEQ_POS_Y 50
191#define SEQ_TRIG_DIST 20
192
193int trig_selection_loc = 1; 247int trig_selection_loc = 1;
194 248
195SeqSprite seq_sprites[34] = {0}; 249SeqSprite seq_sprites[36] = {0};
196 250
197void 251void
198init_sequencer_sprites(void) { 252init_sequencer_sprites(void) {
199 // Sprite note names. 253 // Sprite note names.
200 size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73); 254 size_t sprite_id = load_packed_sprite_data(&sprite_note_names, 2, 73);
201 for (size_t i = 0; i < 16; ++i) { 255 for (size_t i = 0; i < 16; ++i) {
202 int x = SEQ_POS_X + i * SEQ_TRIG_DIST; 256 int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST;
203 int y = SEQ_POS_Y; 257 int y = SEQ_TRIG_POS_Y;
258 int base_tile = sprites[sprite_id].tile_start;
204 if (i >= 8) { 259 if (i >= 8) {
205 y += 32; 260 y += 32;
206 x -= 8 * SEQ_TRIG_DIST; 261 x -= 8 * SEQ_TRIG_DIST;
@@ -209,52 +264,81 @@ init_sequencer_sprites(void) {
209 seq_sprites[i].y = y; 264 seq_sprites[i].y = y;
210 265
211 seq_sprites[i].id = obj_counter++; 266 seq_sprites[i].id = obj_counter++;
267 seq_sprites[i].base_tile = base_tile;
212 seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); 268 seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
213 // TODO: They should start hidden until the update function changes that. 269 // TODO: They should start hidden until the update function changes that.
214 // seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_HIDDEN; 270 // seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_HIDDEN;
215 seq_sprites[i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); 271 seq_sprites[i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x);
216 seq_sprites[i].obj_attr_2 = sprites[sprite_id].tile_start; 272 seq_sprites[i].obj_attr_2 = base_tile;
217 } 273 }
218 274
219 // Trigger boxes. 275 // Trigger boxes.
220 sprite_id = load_packed_sprite_data(&sprite_trigger_button, 8, 1); 276 sprite_id = load_packed_sprite_data(&sprite_trigger_button, 8, 1);
221 for (size_t i = 0; i < 16; ++i) { 277 for (size_t i = 0; i < 16; ++i) {
222 int x = SEQ_POS_X + i * SEQ_TRIG_DIST; 278 int x = SEQ_TRIG_POS_X + i * SEQ_TRIG_DIST;
223 int y = SEQ_POS_Y; 279 int y = SEQ_TRIG_POS_Y;
280 int base_tile = sprites[sprite_id].tile_start;
224 if (i >= 8) { 281 if (i >= 8) {
225 y += 32; 282 y += 32;
226 x -= 8 * SEQ_TRIG_DIST; 283 x -= 8 * SEQ_TRIG_DIST;
227 } 284 }
228 seq_sprites[i + 16].id = obj_counter++; 285 seq_sprites[i + 16].id = obj_counter++;
286 seq_sprites[i + 16].base_tile = base_tile;
229 seq_sprites[i + 16].obj_attr_0 = OBJ_SHAPE_TALL | OBJ_Y_COORD(y); 287 seq_sprites[i + 16].obj_attr_0 = OBJ_SHAPE_TALL | OBJ_Y_COORD(y);
230 seq_sprites[i + 16].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); 288 seq_sprites[i + 16].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
231 seq_sprites[i + 16].obj_attr_2 = sprites[sprite_id].tile_start; 289 seq_sprites[i + 16].obj_attr_2 = base_tile;
232 } 290 }
233 291
234 sprite_id = load_packed_sprite_data(&sprite_trigger_active_indicator, 1, 1); 292 sprite_id = load_packed_sprite_data(&sprite_trigger_active_indicator, 1, 1);
235 // TODO: No need for a for loop.
236 { 293 {
237 int x = SEQ_POS_X; 294 int x = SEQ_TRIG_POS_X;
238 int y = SEQ_POS_Y + 15; 295 int y = SEQ_TRIG_POS_Y + 15;
296 int base_tile = sprites[sprite_id].tile_start;
239 seq_sprites[32].id = obj_counter++; 297 seq_sprites[32].id = obj_counter++;
298 seq_sprites[32].base_tile = base_tile;
240 seq_sprites[32].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); 299 seq_sprites[32].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
241 seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); 300 seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x);
242 seq_sprites[32].obj_attr_2 = sprites[sprite_id].tile_start | OBJ_PAL_BANK(1); 301 seq_sprites[32].obj_attr_2 = base_tile | OBJ_PAL_BANK(1);
243 } 302 }
244 303
245 sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); 304 sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1);
246 // TODO: No need for a for loop.
247 { 305 {
248 int x = SEQ_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; 306 int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST;
249 int y = SEQ_POS_Y - 2; 307 int y = SEQ_TRIG_POS_Y - 2;
308 int base_tile = sprites[sprite_id].tile_start;
250 if (trig_selection_loc >= 8) { 309 if (trig_selection_loc >= 8) {
251 y += 32; 310 y += 32;
252 x -= 8 * SEQ_TRIG_DIST; 311 x -= 8 * SEQ_TRIG_DIST;
253 } 312 }
254 seq_sprites[33].id = obj_counter++; 313 seq_sprites[33].id = obj_counter++;
314 seq_sprites[33].base_tile = base_tile;
255 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); 315 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
256 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); 316 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
257 seq_sprites[33].obj_attr_2 = sprites[sprite_id].tile_start | OBJ_PAL_BANK(2); 317 seq_sprites[33].obj_attr_2 = base_tile | OBJ_PAL_BANK(2);
318 }
319
320 sprite_id = load_packed_sprite_data(&sprite_env_labels, 4, 1);
321 {
322 int x = SEQ_ENV_POS_X;
323 int y = SEQ_ENV_POS_Y;
324 int base_tile = sprites[sprite_id].tile_start;
325 seq_sprites[34].id = obj_counter++;
326 seq_sprites[34].base_tile = base_tile;
327 seq_sprites[34].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
328 seq_sprites[34].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
329 seq_sprites[34].obj_attr_2 = base_tile | OBJ_PAL_BANK(2);
330 }
331
332 sprite_id = load_packed_sprite_data(&sprite_env_volume, 4, 16);
333 {
334 int x = SEQ_ENV_POS_X;
335 int y = SEQ_ENV_POS_Y + 8;
336 int base_tile = sprites[sprite_id].tile_start;
337 seq_sprites[35].id = obj_counter++;
338 seq_sprites[35].base_tile = base_tile;
339 seq_sprites[35].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
340 seq_sprites[35].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x);
341 seq_sprites[35].obj_attr_2 = base_tile | OBJ_PAL_BANK(2);
258 } 342 }
259} 343}
260 344
@@ -279,8 +363,8 @@ update_sequencer_sprites(void) {
279 363
280 // 33: Sequence indicator. 364 // 33: Sequence indicator.
281 { 365 {
282 int x = SEQ_POS_X + step_counter * SEQ_TRIG_DIST + 3; 366 int x = SEQ_TRIG_POS_X + step_counter * SEQ_TRIG_DIST + 3;
283 int y = SEQ_POS_Y + 15; 367 int y = SEQ_TRIG_POS_Y + 15;
284 if (step_counter >= 8) { 368 if (step_counter >= 8) {
285 y += 32; 369 y += 32;
286 x -= 8 * SEQ_TRIG_DIST; 370 x -= 8 * SEQ_TRIG_DIST;
@@ -291,8 +375,8 @@ update_sequencer_sprites(void) {
291 375
292 // 34: Trigger selection. 376 // 34: Trigger selection.
293 { 377 {
294 int x = SEQ_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST; 378 int x = SEQ_TRIG_POS_X - 1 + trig_selection_loc * SEQ_TRIG_DIST;
295 int y = SEQ_POS_Y - 2; 379 int y = SEQ_TRIG_POS_Y - 2;
296 if (trig_selection_loc >= 8) { 380 if (trig_selection_loc >= 8) {
297 y += 32; 381 y += 32;
298 x -= 8 * SEQ_TRIG_DIST; 382 x -= 8 * SEQ_TRIG_DIST;
@@ -301,6 +385,14 @@ update_sequencer_sprites(void) {
301 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); 385 seq_sprites[33].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y);
302 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); 386 seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x);
303 } 387 }
388
389 // 36: Envelope initial volume
390 {
391 size_t tile_diff = sequence_synth[trig_selection_loc].env_volume * 4;
392 size_t base_tile = seq_sprites[35].base_tile;
393 size_t tile = base_tile + tile_diff;
394 seq_sprites[35].obj_attr_2 = tile | OBJ_PAL_BANK(2);
395 }
304} 396}
305 397
306void 398void