diff options
author | Bad Diode <bd@badd10de.dev> | 2021-06-03 15:07:53 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-06-03 15:07:53 +0200 |
commit | 5ca4491aa46b7090189685fecf422ee7316de724 (patch) | |
tree | c9f3b23ab2bbdddca78a06c6f43ad86700ce8c4f | |
parent | 0eda19bd2bb551bf9186b0fbe1a806a28d5a3597 (diff) | |
download | stepper-5ca4491aa46b7090189685fecf422ee7316de724.tar.gz stepper-5ca4491aa46b7090189685fecf422ee7316de724.zip |
Add tile drawing function for the framebuffer
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | src/renderer.c | 76 |
2 files changed, 79 insertions, 13 deletions
@@ -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 @@ | |||
46 | static u32 dirty_tiles[21] = {0}; | 46 | static 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 | ||
51 | IWRAM_CODE | 51 | IWRAM_CODE |
52 | void | 52 | void |
53 | draw_pixel(u16 x, u16 y, u8 color) { | 53 | draw_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 | ||
71 | IWRAM_CODE | 71 | IWRAM_CODE |
72 | void | 72 | void |
73 | draw_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 | |||
143 | IWRAM_CODE | ||
144 | void | ||
73 | flip_buffer(void) { | 145 | flip_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; |