From 5ca4491aa46b7090189685fecf422ee7316de724 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 3 Jun 2021 15:07:53 +0200 Subject: Add tile drawing function for the framebuffer --- src/main.c | 16 ++++--------- src/renderer.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index 6226bcd..913043a 100644 --- a/src/main.c +++ b/src/main.c @@ -13,7 +13,6 @@ WITH REGARD TO THIS SOFTWARE. #include "filesystem.c" #include "renderer.c" -// #include "text.h" // // Config parameters. @@ -65,16 +64,11 @@ int main(void) { irq_init(); irs_set(IRQ_VBLANK, irs_stub); - draw_pixel(10, 0, 1); - draw_pixel(10, 1, 2); - draw_pixel(10, 2, 3); - draw_pixel(10, 3, 4); - draw_pixel( 0, 0, 1); - draw_pixel( 0, 1, 2); - draw_pixel( 0, 2, 3); - draw_pixel( 0, 3, 4); - txt_position(8, 8); - txt_printf("Hello world!"); + Tile *tile = FONT_DATA; + tile += 'A'; + draw_tile(0, 0, tile, true); + draw_tile(0, 4, tile, true); + draw_tile(4, 0, tile, true); // Main loop. PROF_INIT(); diff --git a/src/renderer.c b/src/renderer.c index bd2c023..500cc78 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -46,12 +46,12 @@ static u32 dirty_tiles[21] = {0}; // TODO: Allow disable bound checking at compile time. -#define BOUNDCHECK_SCREEN() if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; +#define BOUNDCHECK_SCREEN(X,Y) if ((X) >= SCREEN_WIDTH || (Y) >= SCREEN_HEIGHT) return; IWRAM_CODE void draw_pixel(u16 x, u16 y, u8 color) { - BOUNDCHECK_SCREEN(); + BOUNDCHECK_SCREEN(x, y); // Find row position for the given x/y coordinates. size_t tile_x = x / 8; @@ -68,6 +68,78 @@ draw_pixel(u16 x, u16 y, u8 color) { dirty_tiles[tile_y] |= 1 << tile_x; } +IWRAM_CODE +void +draw_tile(u16 x, u16 y, Tile *tile, bool merge) { + BOUNDCHECK_SCREEN(x, y); + + // Find row position for the given x/y coordinates. + size_t tile_x = x / 8; + size_t tile_y = y / 8; + size_t start_col = x % 8; + size_t start_row = y % 8; + + // Get a pointer to the backbuffer and the tile row. + size_t pos = start_row + (tile_x + tile_y * 32) * 8; + u32 *backbuffer = &BACKBUF[pos]; + u32 *row = tile; + + // This will blend all colors weirdly if using tiles that contain colors + // higher than 1. + size_t shift_left = start_col * 4; + size_t shift_right = (8 - start_col) * 4; + u32 row_mask = merge ? 0 : 0xFFFFFFFF << shift_left; + + // Draw the tiles. There are 4 possible cases: + // 1. The tile is exactly at the tile boundary. + // 2. The tile spans 2 tiles horizontally. + // 3. The tile spans 2 tiles vertically. + // 4. The tile spans 4 tiles. + if (start_col == 0 && start_row == 0) { + for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i]; + } + dirty_tiles[tile_y] |= 1 << tile_x; + } else if (start_row == 0) { + for (size_t i = 0; i < 8; i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left); + backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right); + } + dirty_tiles[tile_y] |= 1 << tile_x; + dirty_tiles[tile_y] |= 1 << (tile_x + 1); + } else if (start_col == 0) { + for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i]; + } + backbuffer += 8 * 31; + for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i]; + } + dirty_tiles[tile_y] |= 1 << tile_x; + dirty_tiles[tile_y + 1] |= 1 << tile_x; + } else { + for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left); + backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right); + } + backbuffer += 8 * 31; + for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) { + BOUNDCHECK_SCREEN(x, y + i); + backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left); + backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right); + } + dirty_tiles[tile_y] |= 1 << tile_x; + dirty_tiles[tile_y] |= 1 << (tile_x + 1); + dirty_tiles[tile_y + 1] |= 1 << tile_x; + dirty_tiles[tile_y + 1] |= 1 << (tile_x + 1); + } +} + IWRAM_CODE void flip_buffer(void) { -- cgit v1.2.1