summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-06-03 15:07:53 +0200
committerBad Diode <bd@badd10de.dev>2021-06-03 15:07:53 +0200
commit5ca4491aa46b7090189685fecf422ee7316de724 (patch)
treec9f3b23ab2bbdddca78a06c6f43ad86700ce8c4f
parent0eda19bd2bb551bf9186b0fbe1a806a28d5a3597 (diff)
downloadgba-sequencer-5ca4491aa46b7090189685fecf422ee7316de724.tar.gz
gba-sequencer-5ca4491aa46b7090189685fecf422ee7316de724.zip
Add tile drawing function for the framebuffer
-rw-r--r--src/main.c16
-rw-r--r--src/renderer.c76
2 files changed, 79 insertions, 13 deletions
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.
13 13
14#include "filesystem.c" 14#include "filesystem.c"
15#include "renderer.c" 15#include "renderer.c"
16// #include "text.h"
17 16
18// 17//
19// Config parameters. 18// Config parameters.
@@ -65,16 +64,11 @@ int main(void) {
65 irq_init(); 64 irq_init();
66 irs_set(IRQ_VBLANK, irs_stub); 65 irs_set(IRQ_VBLANK, irs_stub);
67 66
68 draw_pixel(10, 0, 1); 67 Tile *tile = FONT_DATA;
69 draw_pixel(10, 1, 2); 68 tile += 'A';
70 draw_pixel(10, 2, 3); 69 draw_tile(0, 0, tile, true);
71 draw_pixel(10, 3, 4); 70 draw_tile(0, 4, tile, true);
72 draw_pixel( 0, 0, 1); 71 draw_tile(4, 0, tile, true);
73 draw_pixel( 0, 1, 2);
74 draw_pixel( 0, 2, 3);
75 draw_pixel( 0, 3, 4);
76 txt_position(8, 8);
77 txt_printf("Hello world!");
78 72
79 // Main loop. 73 // Main loop.
80 PROF_INIT(); 74 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 @@
46static u32 dirty_tiles[21] = {0}; 46static u32 dirty_tiles[21] = {0};
47 47
48// TODO: Allow disable bound checking at compile time. 48// TODO: Allow disable bound checking at compile time.
49#define BOUNDCHECK_SCREEN() if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) return; 49#define BOUNDCHECK_SCREEN(X,Y) if ((X) >= SCREEN_WIDTH || (Y) >= SCREEN_HEIGHT) return;
50 50
51IWRAM_CODE 51IWRAM_CODE
52void 52void
53draw_pixel(u16 x, u16 y, u8 color) { 53draw_pixel(u16 x, u16 y, u8 color) {
54 BOUNDCHECK_SCREEN(); 54 BOUNDCHECK_SCREEN(x, y);
55 55
56 // Find row position for the given x/y coordinates. 56 // Find row position for the given x/y coordinates.
57 size_t tile_x = x / 8; 57 size_t tile_x = x / 8;
@@ -70,6 +70,78 @@ draw_pixel(u16 x, u16 y, u8 color) {
70 70
71IWRAM_CODE 71IWRAM_CODE
72void 72void
73draw_tile(u16 x, u16 y, Tile *tile, bool merge) {
74 BOUNDCHECK_SCREEN(x, y);
75
76 // Find row position for the given x/y coordinates.
77 size_t tile_x = x / 8;
78 size_t tile_y = y / 8;
79 size_t start_col = x % 8;
80 size_t start_row = y % 8;
81
82 // Get a pointer to the backbuffer and the tile row.
83 size_t pos = start_row + (tile_x + tile_y * 32) * 8;
84 u32 *backbuffer = &BACKBUF[pos];
85 u32 *row = tile;
86
87 // This will blend all colors weirdly if using tiles that contain colors
88 // higher than 1.
89 size_t shift_left = start_col * 4;
90 size_t shift_right = (8 - start_col) * 4;
91 u32 row_mask = merge ? 0 : 0xFFFFFFFF << shift_left;
92
93 // Draw the tiles. There are 4 possible cases:
94 // 1. The tile is exactly at the tile boundary.
95 // 2. The tile spans 2 tiles horizontally.
96 // 3. The tile spans 2 tiles vertically.
97 // 4. The tile spans 4 tiles.
98 if (start_col == 0 && start_row == 0) {
99 for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) {
100 BOUNDCHECK_SCREEN(x, y + i);
101 backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i];
102 }
103 dirty_tiles[tile_y] |= 1 << tile_x;
104 } else if (start_row == 0) {
105 for (size_t i = 0; i < 8; i++, backbuffer++) {
106 BOUNDCHECK_SCREEN(x, y + i);
107 backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left);
108 backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right);
109 }
110 dirty_tiles[tile_y] |= 1 << tile_x;
111 dirty_tiles[tile_y] |= 1 << (tile_x + 1);
112 } else if (start_col == 0) {
113 for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) {
114 BOUNDCHECK_SCREEN(x, y + i);
115 backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i];
116 }
117 backbuffer += 8 * 31;
118 for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) {
119 BOUNDCHECK_SCREEN(x, y + i);
120 backbuffer[0] = (backbuffer[0] & ~row_mask) | row[i];
121 }
122 dirty_tiles[tile_y] |= 1 << tile_x;
123 dirty_tiles[tile_y + 1] |= 1 << tile_x;
124 } else {
125 for (size_t i = 0; i < (8 - start_row); i++, backbuffer++) {
126 BOUNDCHECK_SCREEN(x, y + i);
127 backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left);
128 backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right);
129 }
130 backbuffer += 8 * 31;
131 for (size_t i = (8 - start_row); i < 8; i++, backbuffer++) {
132 BOUNDCHECK_SCREEN(x, y + i);
133 backbuffer[0] = (backbuffer[0] & ~row_mask) | (row[i] << shift_left);
134 backbuffer[8] = (backbuffer[8] & row_mask) | (row[i] >> shift_right);
135 }
136 dirty_tiles[tile_y] |= 1 << tile_x;
137 dirty_tiles[tile_y] |= 1 << (tile_x + 1);
138 dirty_tiles[tile_y + 1] |= 1 << tile_x;
139 dirty_tiles[tile_y + 1] |= 1 << (tile_x + 1);
140 }
141}
142
143IWRAM_CODE
144void
73flip_buffer(void) { 145flip_buffer(void) {
74 // Copy dirty tiles from the backbuffer to the frontbuffer. 146 // Copy dirty tiles from the backbuffer to the frontbuffer.
75 Tile *dst = FRONTBUF; 147 Tile *dst = FRONTBUF;