From 269f2326171982912f50c2b6ef0cd272ec3c0108 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Fri, 7 May 2021 18:55:12 +0200 Subject: Initial implementation of mode4 rendering and parameter editing on CH3 --- src/bitmap.h | 64 +++------- src/common.h | 2 + src/main.c | 7 +- src/sequencer.c | 368 +++++++++++++++++++++++++++++++++----------------------- src/text.h | 10 +- 5 files changed, 253 insertions(+), 198 deletions(-) diff --git a/src/bitmap.h b/src/bitmap.h index bae9b40..c839900 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -1,30 +1,8 @@ #ifndef GBAEXP_BITMAP_H #define GBAEXP_BITMAP_H -// #include "bd-font.c" #include "common.h" -// Using bd-font, an 8x8 bitmap font. -// static void -// put_char(int x, int y, Color clr, u8 chr) { -// for (size_t i = 0; i < 8; ++i) { -// for (size_t j = 0; j < 8; ++j) { -// if ((font[chr][i] >> (7 - j)) & 0x1) { -// FRAMEBUFFER[y + i][x + j] = clr; -// } -// } -// } -// } - -// static void -// put_text(int x, int y, Color clr, char *msg) { -// int count = 0; -// while (*msg) { -// put_char(x + count, y, clr, *msg++); -// count += 8; -// } -// } - // Draws a line with the given color between (x0,y0) and (x1,y1) using the // Bresenham's line drawing algorithm using exclusively integer arithmetic. static void @@ -146,17 +124,31 @@ draw_fill_rect(int x0, int y0, int x1, int y1, Color clr) { // GBA needs to meet memory alignment requirements, we can't write a u8 into // memory, instead we need to read a u16 word, mask and or the corresponding // bits and wave the updated u16. -static void -put_pixel_m4(int x, int y, u8 col_index, vu16 *buffer) { +static inline void +put_pixel_m4(int x, int y, u8 clr_idx, vu16 *buffer) { int buffer_index = (y * SCREEN_WIDTH + x) / 2; vu16 *destination = &buffer[buffer_index]; // Odd pixels will go to the top 8 bits of the destination. Even pixels to // the lower 8 bits. int odd = x & 0x1; if(odd) { - *destination= (*destination & 0xFF) | (col_index << 8); + *destination= (*destination & 0xFF) | (clr_idx << 8); } else { - *destination= (*destination & ~0xFF) | col_index; + *destination= (*destination & ~0xFF) | clr_idx; + } +} + +static inline void +put_pixel_m3(int x, int y, u16 color, Scanline *buffer) { + buffer[y][x] = color; +} + +static inline void +clear_screen_m4() { + size_t size = SCREEN_WIDTH * SCREEN_HEIGHT / 8; + u32 *buf = backbuffer; + for (size_t i = 0; i < size; ++i) { + buf[i] = 0; } } @@ -205,24 +197,4 @@ draw_logo(void) { draw_line(x + height, y + 1, x + height + line, y + 1, COLOR_WHITE); } -// void -// copy_font_to_tile_memory(Tile *tile) { -// // Hex to bits translation table. -// const u32 conversion_u32[16] = { -// 0x00000000, 0x00001000, 0x00000100, 0x00001100, -// 0x00000010, 0x00001010, 0x00000110, 0x00001110, -// 0x00000001, 0x00001001, 0x00000101, 0x00001101, -// 0x00000011, 0x00001011, 0x00000111, 0x00001111, -// }; -// for (size_t i = 0; i < 250; ++i) { -// for (size_t j = 0; j < 8; ++j) { -// u8 row = font[i][j]; -// u32 tile_idx = 0x00000000; -// tile_idx = conversion_u32[row & 0xF] << 16; -// tile_idx |= conversion_u32[(row >> 4) & 0xF]; -// (tile + i)->data[j] = tile_idx; -// } -// } -// } - #endif // GBAEXP_BITMAP_H diff --git a/src/common.h b/src/common.h index aa7261e..cf263db 100644 --- a/src/common.h +++ b/src/common.h @@ -147,6 +147,7 @@ typedef Color Scanline[SCREEN_WIDTH]; #define PAL_BUFFER_SPRITES ((u16*)(MEM_PAL + 0x200)) #define PAL_BANK_BG ((Palette*) MEM_PAL) #define PAL_BANK_SPRITES ((Palette*)(MEM_PAL + 0x200)) +static u16 *backbuffer = ((vu16*)(MEM_VRAM + 0x0A000)); // // Sprites. @@ -198,6 +199,7 @@ typedef Color Scanline[SCREEN_WIDTH]; static inline void flip_page(void) { + backbuffer = (u16*)((u32)backbuffer ^ 0x0A000); DISP_CTRL ^= DISP_PAGE; } diff --git a/src/main.c b/src/main.c index 3065842..d4d49cc 100644 --- a/src/main.c +++ b/src/main.c @@ -15,7 +15,12 @@ int main(void) { // Configure the display in mode 0 to show OBJs, where tile memory is // sequential. - DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_3 | DISP_BG_2; + DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_4 | DISP_BG_2; + // DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_3 | DISP_BG_2; + + PAL_BUFFER_BG[1] = COLOR_WHITE; + PAL_BUFFER_BG[2] = COLOR_RED; + PAL_BUFFER_BG[3] = COLOR_CYAN; // Initialize text engine. txt_init_bitmap( diff --git a/src/sequencer.c b/src/sequencer.c index a19cef7..c09fb01 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -15,6 +15,10 @@ #define SEQ_DUTYCYCLE_POS_Y 10 - 8 #define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST #define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y +#define SEQ_CH3_PARAM_X SEQ_TRIG_POS_X +#define SEQ_CH3_PARAM_Y SEQ_ENV_POS_Y +#define SEQ_CH3_PARAM_SEL_X SEQ_CH3_PARAM_X - 5 +#define SEQ_CH3_PARAM_SEL_Y SEQ_CH3_PARAM_Y + 22 #define SEQ_N_CHANNELS 3 u32 sprite_note_names[] = { @@ -522,6 +526,7 @@ set_time(int bpm) { // - 054-054 channel 4. // - 055-055 RESERVED: FM synth?. // - 056-056 channel selector. +// - 057-057 ch3 selector. // @@ -548,18 +553,20 @@ int param_selection_loc = 0; int channel_selection_loc = 2; SeqSelect current_selection = SEQ_SELECT_TRIGGER; -SeqSprite seq_sprites[57] = {0}; +SeqSprite seq_sprites[58] = {0}; void -draw_wave_pattern(u8 *pattern, int x, int y, Color clr) { +draw_wave_pattern(u8 *pattern, int x, int y, u16 clr_idx) { for (size_t i = 0; i < 16; ++i) { u8 byte = pattern[i]; u8 first = (byte >> 4) & 0xF; u8 second = byte & 0xF; - FRAMEBUFFER[y + 16 - first][x + i * 4] = clr; - FRAMEBUFFER[y + 16 - first][x + i * 4 + 1] = clr; - FRAMEBUFFER[y + 16 - second][x + i * 4 + 2] = clr; - FRAMEBUFFER[y + 16 - second][x + i * 4 + 3] = clr; + u8 a = x + i * 4; + u8 b = y + 16; + put_pixel_m4(a, b - first, clr_idx, backbuffer); + put_pixel_m4(a + 1, b - first, clr_idx, backbuffer); + put_pixel_m4(a + 2, b - second, clr_idx, backbuffer); + put_pixel_m4(a + 3, b - second, clr_idx, backbuffer); } } @@ -616,10 +623,20 @@ init_sequencer_sprites(void) { 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_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); seq_sprites[32].obj_attr_2 = base_tile | OBJ_PAL_BANK(1); } + { + int x = SEQ_CH3_PARAM_SEL_X; + int y = SEQ_CH3_PARAM_SEL_Y; + int base_tile = sprites[sprite_id].tile_start; + seq_sprites[57].id = obj_counter++; + seq_sprites[57].base_tile = base_tile; + seq_sprites[57].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); + } sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); { @@ -632,7 +649,7 @@ init_sequencer_sprites(void) { } 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_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[33].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); seq_sprites[33].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } @@ -644,7 +661,7 @@ init_sequencer_sprites(void) { 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_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[34].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[34].obj_attr_2 = base_tile; } @@ -656,7 +673,7 @@ init_sequencer_sprites(void) { 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_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[35].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[35].obj_attr_2 = base_tile; } @@ -668,7 +685,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[36].id = obj_counter++; seq_sprites[36].base_tile = base_tile; - seq_sprites[36].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[36].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[36].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[36].obj_attr_2 = base_tile; } @@ -678,7 +695,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[45].id = obj_counter++; seq_sprites[45].base_tile = base_tile; - seq_sprites[45].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[45].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[45].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[45].obj_attr_2 = base_tile; } @@ -690,7 +707,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[37].id = obj_counter++; seq_sprites[37].base_tile = base_tile; - seq_sprites[37].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[37].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[37].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[37].obj_attr_2 = base_tile; } @@ -702,7 +719,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[38].id = obj_counter++; seq_sprites[38].base_tile = base_tile; - seq_sprites[38].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[38].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[38].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[38].obj_attr_2 = base_tile; } @@ -712,7 +729,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[47].id = obj_counter++; seq_sprites[47].base_tile = base_tile; - seq_sprites[47].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[47].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[47].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[47].obj_attr_2 = base_tile; } @@ -724,7 +741,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[39].id = obj_counter++; seq_sprites[39].base_tile = base_tile; - seq_sprites[39].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[39].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[39].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[39].obj_attr_2 = base_tile; } @@ -734,7 +751,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[48].id = obj_counter++; seq_sprites[48].base_tile = base_tile; - seq_sprites[48].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[48].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[48].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[48].obj_attr_2 = base_tile; } @@ -746,7 +763,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[40].id = obj_counter++; seq_sprites[40].base_tile = base_tile; - seq_sprites[40].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[40].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[40].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[40].obj_attr_2 = base_tile; } @@ -758,7 +775,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[41].id = obj_counter++; seq_sprites[41].base_tile = base_tile; - seq_sprites[41].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[41].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[41].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); seq_sprites[41].obj_attr_2 = base_tile; } @@ -770,7 +787,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[42].id = obj_counter++; seq_sprites[42].base_tile = base_tile; - seq_sprites[42].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[42].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[42].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[42].obj_attr_2 = base_tile; } @@ -782,7 +799,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[43].id = obj_counter++; seq_sprites[43].base_tile = base_tile; - seq_sprites[43].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[43].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[43].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[43].obj_attr_2 = base_tile; } @@ -794,7 +811,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[44].id = obj_counter++; seq_sprites[44].base_tile = base_tile; - seq_sprites[44].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[44].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[44].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); seq_sprites[44].obj_attr_2 = base_tile; } @@ -804,7 +821,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[46].id = obj_counter++; seq_sprites[46].base_tile = base_tile; - seq_sprites[46].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[46].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[46].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); seq_sprites[46].obj_attr_2 = base_tile; } @@ -816,7 +833,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[49].id = obj_counter++; seq_sprites[49].base_tile = base_tile; - seq_sprites[49].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[49].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[49].obj_attr_1 = OBJ_SIZE_MID | OBJ_X_COORD(x); seq_sprites[49].obj_attr_2 = base_tile; } @@ -828,7 +845,7 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[50].id = obj_counter++; seq_sprites[50].base_tile = base_tile; - seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); seq_sprites[50].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } @@ -1017,19 +1034,7 @@ update_sequencer_sprites(void) { seq_sprites[48].obj_attr_2 = tile; } - // 51: Parameter selector. - { - int x = SEQ_ENV_POS_X + 1 + (param_selection_loc % 7) * SEQ_ENV_DIST; - int y = SEQ_ENV_POS_Y - 3; - int hidden = 0; - if (current_selection != SEQ_SELECT_PARAMETER) { - hidden = OBJ_HIDDEN; - } - seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; - seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); - } - - // 57: Parameter selector. + // 57: Channel selector. { int x = SEQ_CHANNEL_POS_X; int y = SEQ_CHANNEL_POS_Y - 2; @@ -1044,31 +1049,17 @@ update_sequencer_sprites(void) { } } - // TODO: Hide all parameter control sprites for now, we unhide it later. - // Very inefficient but we may change the parameter rendering of all modes - // to use bitmaps instead of sprites later. - for (size_t i = 34; i <= 50; ++i) { - seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN; - } - - if (update_params_screen) { - // Clear screen. - // draw_fill_rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2, COLOR_BLACK); - int zero = 0; - dma_fill(FRAMEBUFFER, zero, SCREEN_WIDTH * SCREEN_HEIGHT * 2, 3); - - } if (channel_selection_loc == 2) { if (update_params_screen) { u8 *wave_a = sequences[channel_selection_loc][trig_selection_loc].wave_a; u8 *wave_b = sequences[channel_selection_loc][trig_selection_loc].wave_b; // Draw wave patterns for this trig. - int x = SEQ_ENV_POS_X; - int y = SEQ_ENV_POS_Y; + int x = SEQ_CH3_PARAM_X; + int y = SEQ_CH3_PARAM_Y; // Wave A. - draw_wave_pattern(wave_a, x, y, COLOR_RED); + draw_wave_pattern(wave_a, x, y, 2); txt_position(x - 1, y + 20); txt_printf("%02x%02x%02x%02x %02x%02x%02x%02x", wave_a[0], wave_a[1], wave_a[2], wave_a[3], @@ -1079,8 +1070,8 @@ update_sequencer_sprites(void) { wave_a[12], wave_a[13], wave_a[14], wave_a[15]); // Wave B. - x += 64 + 32 + 12; - draw_wave_pattern(wave_b, x, y, COLOR_CYAN); + x += 64 + 12; + draw_wave_pattern(wave_b, x, y, 3); txt_position(x - 1, y + 20); txt_printf("%02x%02x%02x%02x %02x%02x%02x%02x", wave_b[0], wave_b[1], wave_b[2], wave_b[3], @@ -1089,27 +1080,66 @@ update_sequencer_sprites(void) { txt_printf("%02x%02x%02x%02x %02x%02x%02x%02x", wave_b[8], wave_b[9], wave_b[10], wave_b[11], wave_b[12], wave_b[13], wave_b[14], wave_b[15]); + + // Clear the backbuffer. + flip_page(); + clear_screen_m4(); } - } else if ((current_selection == SEQ_SELECT_TRIGGER - || current_selection == SEQ_SELECT_PARAMETER) - && channel_selection_loc == 0) { - for (size_t i = 34; i <= 50; ++i) { - seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; + + // Update parameter selection. + { + int x = SEQ_CH3_PARAM_SEL_X + param_selection_loc * 4; + int y = SEQ_CH3_PARAM_SEL_Y; + int base_tile = seq_sprites[57].base_tile; + int hidden = 0; + if (current_selection != SEQ_SELECT_PARAMETER) { + hidden = OBJ_HIDDEN; + } + seq_sprites[57].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; + seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } - } else if ((current_selection == SEQ_SELECT_TRIGGER - || current_selection == SEQ_SELECT_PARAMETER) - && channel_selection_loc == 1) { - for (size_t i = 34; i < 43; ++i) { - seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; + } + + if (channel_selection_loc == 0) { + if (current_selection == SEQ_SELECT_TRIGGER + || current_selection == SEQ_SELECT_PARAMETER) { + for (size_t i = 34; i < 50; ++i) { + seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; + } } - seq_sprites[50].obj_attr_0 &= ~OBJ_HIDDEN; - } else { - int x = SEQ_ENV_POS_X + 8; - int y = SEQ_ENV_POS_Y; + } - // Clear parameters for channel 3. - draw_fill_rect(x, y, x + 64, y + 16, COLOR_BLACK); - draw_fill_rect(x + 64 + 16, y, x + 64 * 2 + 16, y + 16, COLOR_BLACK); + if (channel_selection_loc == 1) { + if (current_selection == SEQ_SELECT_TRIGGER + || current_selection == SEQ_SELECT_PARAMETER) { + for (size_t i = 34; i <= 42; ++i) { + seq_sprites[i].obj_attr_0 &= ~OBJ_HIDDEN; + } + } + } + + if (channel_selection_loc == 0 || channel_selection_loc == 1) { + // 51: Parameter selector. + int x = SEQ_ENV_POS_X + 1 + (param_selection_loc % 7) * SEQ_ENV_DIST; + int y = SEQ_ENV_POS_Y - 3; + int hidden = 0; + if (current_selection != SEQ_SELECT_PARAMETER) { + hidden = OBJ_HIDDEN; + } + seq_sprites[50].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; + seq_sprites[50].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); + } + + if (current_selection == SEQ_SELECT_CHANNEL && update_params_screen) { + // TODO: Hide all parameter control sprites for now, we unhide it later. + // Very inefficient but we may change the parameter rendering of all + // modes to use bitmaps instead of sprites later. + for (size_t i = 34; i <= 50; ++i) { + seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN; + } + flip_page(); + clear_screen_m4(); } update_params_screen = false; } @@ -1133,91 +1163,129 @@ handle_sequencer_input(void) { } else if (key_pressed(KEY_B)) { trig->trigger ^= 1; } else if (key_pressed(KEY_L)) { - trig->note = MAX(trig->note - 1, NOTE_C_2); + if (trig->trigger) { + trig->note = MAX(trig->note - 1, NOTE_C_2); + } } else if (key_pressed(KEY_R)) { - trig->note = MIN( trig->note + 1, NOTE_C_8); + if (trig->trigger) { + trig->note = MIN( trig->note + 1, NOTE_C_8); + } } else if (key_pressed(KEY_A)) { // Switch to parameter selection. current_selection = SEQ_SELECT_PARAMETER; } } else if (current_selection == SEQ_SELECT_PARAMETER) { - // Move through the selected synth parameters. - if (key_pressed(KEY_LEFT)) { - int max_param = 6; - if (channel_selection_loc == 1) { - max_param = 3; + if (channel_selection_loc < 2) { + // Move through the selected synth parameters. + if (key_pressed(KEY_LEFT)) { + int max_param = 6; + if (channel_selection_loc == 1) { + max_param = 3; + } + if (param_selection_loc == 0) { + param_selection_loc = max_param; + } else { + param_selection_loc = MAX(param_selection_loc - 1, 0); + } } - if (param_selection_loc == 0) { - param_selection_loc = max_param; - } else { - param_selection_loc = MAX(param_selection_loc - 1, 0); + if (key_pressed(KEY_RIGHT)) { + int max_param = 6; + if (channel_selection_loc == 1) { + max_param = 3; + } + if (param_selection_loc == max_param) { + param_selection_loc = 0; + } else { + param_selection_loc = MIN(param_selection_loc + 1, max_param); + } } - } - if (key_pressed(KEY_RIGHT)) { - int max_param = 6; - if (channel_selection_loc == 1) { - max_param = 3; + + // Adjust the parameters up or down. + if (key_pressed(KEY_L)) { + switch (param_selection_loc) { + case 0: { + trig->env_volume = MAX(trig->env_volume - 1, 0); + } break; + case 1: { + trig->env_time = MAX(trig->env_time - 1, 0); + } break; + case 2: { + trig->env_direction ^= 1; + } break; + case 3: { + trig->duty_cycle = MAX(trig->duty_cycle - 1, 0); + } break; + case 4: { + trig->sweep_number = MAX(trig->sweep_number - 1, 0); + } break; + case 5: { + trig->sweep_time = MAX(trig->sweep_time - 1, 0); + } break; + case 6: { + if (trig->sweep_direction == 0) { + trig->sweep_direction = 1; + } else { + trig->sweep_direction = 0; + } + } break; + } } - if (param_selection_loc == max_param) { - param_selection_loc = 0; - } else { - param_selection_loc = MIN(param_selection_loc + 1, max_param); + if (key_pressed(KEY_R)) { + switch (param_selection_loc) { + case 0: { + trig->env_volume = MIN(trig->env_volume + 1, 15); + } break; + case 1: { + trig->env_time = MIN(trig->env_time + 1, 7); + } break; + case 2: { + trig->env_direction ^= 1; + } break; + case 3: { + trig->duty_cycle = MIN(trig->duty_cycle + 1, 3); + } break; + case 4: { + trig->sweep_number = MIN(trig->sweep_number + 1, 7); + } break; + case 5: { + trig->sweep_time = MIN(trig->sweep_time + 1, 7); + } break; + case 6: { + trig->sweep_direction ^= 1; + } break; + } } - } - - // Adjust the parameters up or down. - if (key_pressed(KEY_L)) { - switch (param_selection_loc) { - case 0: { - trig->env_volume = MAX(trig->env_volume - 1, 0); - } break; - case 1: { - trig->env_time = MAX(trig->env_time - 1, 0); - } break; - case 2: { - trig->env_direction ^= 1; - } break; - case 3: { - trig->duty_cycle = MAX(trig->duty_cycle - 1, 0); - } break; - case 4: { - trig->sweep_number = MAX(trig->sweep_number - 1, 0); - } break; - case 5: { - trig->sweep_time = MAX(trig->sweep_time - 1, 0); - } break; - case 6: { - if (trig->sweep_direction == 0) { - trig->sweep_direction = 1; - } else { - trig->sweep_direction = 0; - } - } break; + } else if (channel_selection_loc == 2) { + // TODO:... + if (key_pressed(KEY_LEFT)) { + param_selection_loc -= 1; + // int max_param = 6; + // if (channel_selection_loc == 1) { + // max_param = 3; + // } + // if (param_selection_loc == 0) { + // param_selection_loc = max_param; + // } else { + // param_selection_loc = MAX(param_selection_loc - 1, 0); + // } } - } - if (key_pressed(KEY_R)) { - switch (param_selection_loc) { - case 0: { - trig->env_volume = MIN(trig->env_volume + 1, 15); - } break; - case 1: { - trig->env_time = MIN(trig->env_time + 1, 7); - } break; - case 2: { - trig->env_direction ^= 1; - } break; - case 3: { - trig->duty_cycle = MIN(trig->duty_cycle + 1, 3); - } break; - case 4: { - trig->sweep_number = MIN(trig->sweep_number + 1, 7); - } break; - case 5: { - trig->sweep_time = MIN(trig->sweep_time + 1, 7); - } break; - case 6: { - trig->sweep_direction ^= 1; - } break; + if (key_pressed(KEY_RIGHT)) { + param_selection_loc += 1; + // int max_param = 6; + // if (channel_selection_loc == 1) { + // max_param = 3; + // } + // if (param_selection_loc == max_param) { + // param_selection_loc = 0; + // } else { + // param_selection_loc = MIN(param_selection_loc + 1, max_param); + // } + } + if (key_pressed(KEY_R)) { + sequences[2][trig_selection_loc].wave_a[param_selection_loc] += 1; + } + if (key_pressed(KEY_L)) { + sequences[2][trig_selection_loc].wave_a[param_selection_loc] -= 1; } } @@ -1234,6 +1302,7 @@ handle_sequencer_input(void) { if (key_pressed(KEY_RIGHT)) { current_selection = SEQ_SELECT_TRIGGER; trig_selection_loc = 0; + param_selection_loc = 0; } if (key_pressed(KEY_UP)) { if (channel_selection_loc == 0) { @@ -1294,6 +1363,7 @@ render_sequencer_sprites(void) { void init_sequencer() { init_sequencer_sprites(); SOUND_STATUS = SOUND_ENABLE; - SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | SOUND_SQUARE2 | SOUND_WAVE, 3); + SOUND_DMG_MASTER = sound_volume( + SOUND_SQUARE1 | SOUND_SQUARE2 | SOUND_WAVE, 3); SOUND_DSOUND_MASTER = SOUND_DMG25; } diff --git a/src/text.h b/src/text.h index 3c0b3a8..9aa3fdd 100644 --- a/src/text.h +++ b/src/text.h @@ -5,6 +5,7 @@ #include #include "common.h" +#include "bitmap.h" typedef enum { TXT_MODE_TILED_BG, @@ -15,7 +16,7 @@ typedef struct Font { // A pointer to an area of memory containing font data. // TODO: Should we unpack each char everytime or unpack everything into RAM? // Maybe this should be optional? - u32 *data; + u16 *data; // The char_map stores the index to the character position within the font // array depending on the ascii number we want to render. This allows // the usage reduced font sets, for example just uppercase letters and @@ -93,7 +94,12 @@ txt_putc_m3(char c) { for (size_t i = 0; i < text_engine.font.char_height; ++i) { for (size_t j = 0; j < text_engine.font.char_width; ++j) { if ((tile.row[i] >> 4 * j) & 0x1) { - FRAMEBUFFER[y + i][x + j] = text_engine.font.color; + put_pixel_m4(x + j, y + i, 1, backbuffer); + // TODO: Clean this up please. + // put_pixel_m3(x + j, + // y + i, + // text_engine.font.color, + // FRAMEBUFFER); } } } -- cgit v1.2.1