diff options
Diffstat (limited to 'src/renderer.c')
-rw-r--r-- | src/renderer.c | 76 |
1 files changed, 74 insertions, 2 deletions
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; |