summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-04-15 13:38:20 +0200
committerBad Diode <bd@badd10de.dev>2021-04-15 13:38:20 +0200
commitdd5bf6cfc680451f7fc69f3251d103739ae6446b (patch)
treeaacd0b1113bd1f93cba196f29b49597f0175a816
parente8b456ee7c9c45600b1e18727cb494137f062cbd (diff)
downloadgba-experiments-dd5bf6cfc680451f7fc69f3251d103739ae6446b.tar.gz
gba-experiments-dd5bf6cfc680451f7fc69f3251d103739ae6446b.zip
Implement Bresenham's line drawing algorithm
-rw-r--r--src/main.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/src/main.c b/src/main.c
index ea43821..06fe7d9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -84,7 +84,7 @@ put_char(int x, int y, Color clr, u8 chr) {
84} 84}
85 85
86static inline void 86static inline void
87put_line(int x, int y, Color clr, char *msg) { 87put_text(int x, int y, Color clr, char *msg) {
88 int count = 0; 88 int count = 0;
89 while (*msg) { 89 while (*msg) {
90 put_char(x + count, y, clr, *msg++); 90 put_char(x + count, y, clr, *msg++);
@@ -92,6 +92,75 @@ put_line(int x, int y, Color clr, char *msg) {
92 } 92 }
93} 93}
94 94
95// Draws a line with the given color between (x0,y0) and (x1,y1) using the
96// Bresenham's line drawing algorithm using exclusively integer arithmetic.
97static inline void
98draw_line(int x0, int y0, int x1, int y1, Color clr) {
99 // Keep track of the coordinate for writing to the memory buffer.
100 int x = x0;
101 int y = y0;
102
103 // Normalize the drawing direction to always draw from (x0, y0)->(x1, y1)
104 int x_step = 1;
105 int y_step = 1;
106 int dx = x1 - x0;
107 int dy = y1 - y0;
108 if (x0 > x1) {
109 x_step = -1;
110 dx = x0 - x1;
111 }
112 if (y0 > y1) {
113 y_step = -1;
114 dy = y0 - y1;
115 }
116
117 // Precalculate line deltas.
118 int ddx = dx + dx;
119 int ddy = dy + dy;
120
121 // These variables are dependant on the slope. We can avoid considering
122 // separate cases for positive and negative slopes by using pointers to
123 // update the step in x or y.
124 int diff;
125 int diff_inc_a;
126 int diff_inc_b;
127 int n_steps;
128 int *a;
129 int *b;
130 int a_step;
131 int b_step;
132 if (dx >= dy) {
133 diff = ddy - dx;
134 diff_inc_a = ddy;
135 diff_inc_b = ddx;
136 n_steps = dx;
137 a = &x;
138 b = &y;
139 a_step = x_step;
140 b_step = y_step;
141 } else {
142 diff = ddx - dy;
143 diff_inc_a = ddx;
144 diff_inc_b = ddy;
145 n_steps = dy;
146 a = &y;
147 b = &x;
148 a_step = y_step;
149 b_step = x_step;
150 }
151
152 // Draw the line with Bresenham's algorithm.
153 for (size_t i = 0; i <= n_steps; ++i) {
154 FRAMEBUFFER[y][x] = clr;
155 *a += a_step;
156 diff += diff_inc_a;
157 if (diff > 0) {
158 *b += b_step;
159 diff -= diff_inc_b;
160 }
161 }
162}
163
95static inline void 164static inline void
96wait_vsync() { 165wait_vsync() {
97 while(DISP_VCOUNT >= 160); 166 while(DISP_VCOUNT >= 160);
@@ -105,11 +174,26 @@ wait_vsync() {
105int main(void) { 174int main(void) {
106 set_display_mode(DISP_MODE_3 | DISP_BG2); 175 set_display_mode(DISP_MODE_3 | DISP_BG2);
107 176
177
178 put_text(0, 0, rgb15(18, 0, 0), "\n\n\n\n");
179
180 draw_line(0, 0, 3, 8,rgb15(0, 30, 0));
181 draw_line(8, 0, 16, 8,rgb15(0, 0, 30));
182
183 draw_line(0, 0, 8, 3,rgb15(0, 0, 30));
184 draw_line(8, 0, 16, 8,rgb15(0, 0, 30));
185
186 // Testing a "rectangle"
187 draw_line(0, 0, 0, 7,rgb15(0, 0, 30));
188 draw_line(0, 0, 7, 0,rgb15(0, 30, 30));
189 draw_line(0, 7, 7, 7,rgb15(30, 0, 0));
190 draw_line(7, 0, 7, 7,rgb15(0, 30, 0));
191
192 draw_line(8, 7, 15, 0,rgb15(0, 0, 30));
193
194 char scanline_counter[16];
108 while(true) { 195 while(true) {
109 wait_vsync(); 196 wait_vsync();
110 put_line(16, 20 + 16, rgb15(28, 0, 0), "Hello world from the GBA!");
111 put_line(16, 20 + 32, rgb15(0, 28, 28), "Using my little 8x8 bd-font");
112 put_line(16, 20 + 64, rgb15(16, 0, 28), "Isn't that neat? :D");
113 }; 197 };
114 198
115 return 0; 199 return 0;