summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-18 09:30:27 +0200
committerBad Diode <bd@badd10de.dev>2023-04-18 09:30:27 +0200
commit838c38045bef10fa893b6790fe42a5a649ccaeca (patch)
tree11c5529468498724e72d978b7779fff3eeefc852
parent195f219514d02826571a89ff380debfbb2882872 (diff)
downloadgba-link-cable-tester-838c38045bef10fa893b6790fe42a5a649ccaeca.tar.gz
gba-link-cable-tester-838c38045bef10fa893b6790fe42a5a649ccaeca.zip
Change dx >= dy mode 4 line drawing to be subpixel accurate
-rw-r--r--src/renderer_m4.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/renderer_m4.c b/src/renderer_m4.c
index 4e8868a..a70cff9 100644
--- a/src/renderer_m4.c
+++ b/src/renderer_m4.c
@@ -118,6 +118,84 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
118 MAYBE_SWAP(y0, y1); 118 MAYBE_SWAP(y0, y1);
119 draw_vline(x0, y0, y1, clr); 119 draw_vline(x0, y0, y1, clr);
120 } else { 120 } else {
121#if 1
122 // Fixed Precision constants.
123 const int fp_bit = 6;
124 const int fp_one = FP_NUM(1, fp_bit);
125 const int fp_half = fp_one >> 1;
126
127 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
128 int dy = y0 > y1 ? y0 - y1 : y1 - y0;
129 int dxf = (dx << fp_bit);
130 int dyf = (dy << fp_bit);
131
132 if ((dx >= dy && x0 > x1) || (dx < dy && y0 > y1)) {
133 SWAP(x0, x1);
134 SWAP(y0, y1);
135 }
136
137 int frac_x = x0 > x1 ? FP_NUM(x0 - x1, fp_bit) : FP_NUM(x1 - x0, fp_bit);
138 int frac_y = y0 > y1 ? FP_NUM(y0 - y1, fp_bit) : FP_NUM(y1 - y0, fp_bit);
139 int x_step = x0 > x1 ? -1 : 1;
140 int y_step = y0 > y1 ? -SCREEN_WIDTH : SCREEN_WIDTH;
141 int distance = (frac_y - fp_one) * dx - (frac_x - fp_half) * dy;
142
143 u16 *dst = NULL;
144 uintptr_t addr = ((uintptr_t)backbuf + y0 * SCREEN_WIDTH + x0);
145 u32 mask = x0 & 1 ? ~0xFF : 0xFF;
146 u32 color = (clr & 0xFF) | ((clr & 0xFF) << 8);
147 if (dx >= dy) {
148 // int step = dxf / dyf;
149 // int remaining = dx;
150 // int y_step = y0 > y1 ? -1 : 1;
151 // while (remaining > (step - 1)) {
152 // distance += step * 2 * dyf;
153 // if (distance >= 0) {
154 // draw_hline(x0, x0 + step - 1, y0, clr);
155 // x0 += x_step * step;
156 // remaining -= step;
157 // } else {
158 // if (remaining < step) {
159 // break;
160 // }
161 // draw_hline(x0, x0 + step, y0, clr);
162 // distance += 2 * dyf;
163 // x0 += x_step * (step + 1);
164 // remaining -= step + 1;
165 // }
166 // distance -= 2 * dxf;
167 // y0 += y_step;
168 // }
169 // if (remaining >= 0) {
170 // draw_hline(x0, x0 + remaining, y0, clr);
171 // }
172 // int distance = 2 * dy - dx;
173 for (int i = 0; i < dx + 1; i++) {
174 dst = (u16*)(addr - (mask >> 31));
175 *dst = (*dst & ~mask) | (color & mask);
176 if (distance >= 0) {
177 distance -= 2 * dxf;
178 addr += y_step;
179 }
180 distance += 2 * dyf;
181 addr += x_step;
182 mask = ~mask;
183 }
184 } else {
185 int diff = 2 * dx - dy;
186 for (int i = 0; i < dy + 1; i++) {
187 dst = (u16*)(addr - (mask >> 31));
188 *dst = (*dst & ~mask) | (color & mask);
189 if (diff >= 0) {
190 diff -= 2 * dy;
191 addr += x_step;
192 mask = ~mask;
193 }
194 diff += 2 * dx;
195 addr += y_step;
196 }
197 }
198#else
121 // Diagonal line. 199 // Diagonal line.
122 int dx = x0 > x1 ? x0 - x1 : x1 - x0; 200 int dx = x0 > x1 ? x0 - x1 : x1 - x0;
123 int dy = y0 > y1 ? y0 - y1 : y1 - y0; 201 int dy = y0 > y1 ? y0 - y1 : y1 - y0;
@@ -155,6 +233,7 @@ draw_line(size_t x0, size_t y0, size_t x1, size_t y1, u8 clr) {
155 addr += y_step; 233 addr += y_step;
156 } 234 }
157 } 235 }
236#endif
158 } 237 }
159} 238}
160 239