maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
retrosft.h
Go to the documentation of this file.
1
2#ifndef RETROSFT_H
3#define RETROSFT_H
4
5#ifndef RETROSOFT_PRESENT
6# error "RETROSOFT_PRESENT must be defined in order to use retrosoft!"
7#endif /* !RETROSOFT_PRESENT */
8
18
23
24#define RETROFLAT_LINE_X 0
25#define RETROFLAT_LINE_Y 1
26
27#ifndef RETROSOFT_TRACE_LVL
28# define RETROSOFT_TRACE_LVL 0
29#endif /* RETROSOFT_TRACE_LVL */
30
37 retroflat_blit_t* target, RETROFLAT_COLOR color,
38 int x1, int y1, int x2, int y2, uint8_t flags );
39
46 retroflat_blit_t* target, const RETROFLAT_COLOR color_idx,
47 int x, int y, int w, int h, uint8_t flags );
48
57 retroflat_blit_t* target, RETROFLAT_COLOR color,
58 int x, int y, int w, int h, uint8_t flags );
59 /* maug_retrosft */
61
62#ifdef RETROSFT_C
63
64/* === */
65
66void retrosoft_line_strategy(
67 int x1, int y1, int x2, int y2,
68 uint8_t* p_for_axis, uint8_t* p_off_axis, int16_t dist[2],
69 int16_t start[2], int16_t end[2], int16_t iter[2],
70 int16_t* p_inc, int16_t* p_delta
71) {
72
73 /* Figure out strategy based on line slope. */
74 if( abs( y2 - y1 ) < abs( x2 - x1 ) ) {
75 if( x1 > x2 ) {
76 start[RETROFLAT_LINE_X] = x2;
77 start[RETROFLAT_LINE_Y] = y2;
78 end[RETROFLAT_LINE_X] = x1;
79 end[RETROFLAT_LINE_Y] = y1;
80 *p_for_axis = RETROFLAT_LINE_X;
81 } else {
82 start[RETROFLAT_LINE_X] = x1;
83 start[RETROFLAT_LINE_Y] = y1;
84 end[RETROFLAT_LINE_X] = x2;
85 end[RETROFLAT_LINE_Y] = y2;
86 *p_for_axis = RETROFLAT_LINE_X;
87 }
88 } else {
89 if( y2 < y1 ) {
90 start[RETROFLAT_LINE_X] = x2;
91 start[RETROFLAT_LINE_Y] = y2;
92 end[RETROFLAT_LINE_X] = x1;
93 end[RETROFLAT_LINE_Y] = y1;
94 *p_for_axis = RETROFLAT_LINE_Y;
95 } else {
96 start[RETROFLAT_LINE_X] = x1;
97 start[RETROFLAT_LINE_Y] = y1;
98 end[RETROFLAT_LINE_X] = x2;
99 end[RETROFLAT_LINE_Y] = y2;
100 *p_for_axis = RETROFLAT_LINE_Y;
101 }
102 }
103
104 /* C89 requires const initializers, so do math down here. */
105 *p_off_axis = 1 - *p_for_axis;
106 iter[RETROFLAT_LINE_X] = start[RETROFLAT_LINE_X];
107 iter[RETROFLAT_LINE_Y] = start[RETROFLAT_LINE_Y];
108 dist[RETROFLAT_LINE_X] = end[RETROFLAT_LINE_X] - start[RETROFLAT_LINE_X];
109 dist[RETROFLAT_LINE_Y] = end[RETROFLAT_LINE_Y] - start[RETROFLAT_LINE_Y];
110
111 /* Adjust delta/slope for off-axis. */
112 *p_delta = (2 * dist[*p_off_axis]) - dist[*p_for_axis];
113 if( 0 > dist[*p_off_axis] ) {
114 *p_inc = -1;
115 dist[*p_off_axis] *= -1;
116 } else {
117 *p_inc = 1;
118 }
119
120
121}
122
123#if defined( RETROFLAT_OPENGL ) || \
124 defined( RETROFLAT_API_PC_BIOS ) || \
125 defined( RETROFLAT_SOFT_LINES )
126
127void retrosoft_line(
128 retroflat_blit_t* target, RETROFLAT_COLOR color,
129 int x1, int y1, int x2, int y2, uint8_t flags
130) {
131
132 uint8_t for_axis = 0,
133 off_axis = 0;
134 int16_t dist[2],
135 start[2],
136 end[2],
137 iter[2],
138 inc = 1,
139 delta = 0;
140
141 /* TODO: Handle thickness. */
142
143#ifndef RETROFLAT_3D
144 /* Under 3D mode, we should never be drawing directly to the screen! */
145 if( NULL == target ) {
146 target = retroflat_screen_buffer();
147 }
148#endif /* !RETROFLAT_3D */
149
150 retroflat_px_lock( target );
151
152 retrosoft_line_strategy(
153 x1, y1, x2, y2,
154 &for_axis, &off_axis, dist, start, end, iter, &inc, &delta );
155
156 for(
157 iter[for_axis] = start[for_axis] ;
158 end[for_axis] > iter[for_axis] ;
159 iter[for_axis]++
160 ) {
161
162 /*
163 if(
164 (size_t)iter[RETROFLAT_LINE_X] < (size_t)retroflat_screen_w() &&
165 (size_t)iter[RETROFLAT_LINE_Y] < (size_t)retroflat_screen_h()
166 ) {
167 */
169 target, color,
170 iter[RETROFLAT_LINE_X], iter[RETROFLAT_LINE_Y], 0 );
171 /* } */
172
173 /* Increment off-axis based on for-axis. */
174 if( 0 < delta ) {
175 iter[off_axis] += inc;
176 delta += (2 * (dist[off_axis] - dist[for_axis]));
177 } else {
178 delta += (2 * dist[off_axis]);
179 }
180 }
181
182 retroflat_px_release( target );
183}
184
185#endif /* RETROFLAT_OPENGL || RETROFLAT_SOFT_LINES */
186
187/* === */
188
189void retrosoft_rect(
190 retroflat_blit_t* target, const RETROFLAT_COLOR color_idx,
191 int x, int y, int w, int h, uint8_t flags
192) {
193 int x_iter = 0,
194 y_iter = 0;
195
196#ifndef RETROFLAT_3D
197 /* Under 3D mode, we should never be drawing directly to the screen! */
198 if( NULL == target ) {
199 target = retroflat_screen_buffer();
200 }
201#endif /* !RETROFLAT_3D */
202
203 retroflat_px_lock( target );
204
205 if( RETROFLAT_FLAGS_FILL == (RETROFLAT_FLAGS_FILL & flags) ) {
206
207 for( y_iter = y ; y_iter < y + h ; y_iter++ ) {
208 for( x_iter = x ; x_iter < x + w ; x_iter++ ) {
209 /* TODO: Optimize filling 4-byte sequences! */
210 retroflat_2d_px( target, color_idx, x_iter, y_iter, 0 );
211 }
212 }
213
214 } else {
215
216#if defined( RETROFLAT_SOFT_LINES ) || defined( RETROFLAT_3D )
217 retrosoft_line( target, color_idx, x, y, x + w, y, 0 );
218 retrosoft_line( target, color_idx, x + w, y, x + w, y + h, 0 );
219 retrosoft_line( target, color_idx, x + w, y + h, x, y + h, 0 );
220 retrosoft_line( target, color_idx, x, y + h, x, y, 0 );
221#else
222 retroflat_line( target, color_idx, x, y, x + w, y, 0 );
223 retroflat_line( target, color_idx, x + w, y, x + w, y + h, 0 );
224 retroflat_line( target, color_idx, x + w, y + h, x, y + h, 0 );
225 retroflat_line( target, color_idx, x, y + h, x, y, 0 );
226#endif
227
228 }
229
230 retroflat_px_release( target );
231}
232
233/* === */
234
236 retroflat_blit_t* target, RETROFLAT_COLOR color,
237 int x, int y, int w, int h, uint8_t flags
238) {
239 int32_t i = 0,
240 i_prev = 0;
241 uint16_t px_x1 = 0,
242 px_y1 = 0,
243 px_x2 = 0,
244 px_y2 = 0;
245
246 /* TODO: Switch to Bresenham algorithm. */
247
248 /* TODO: Filled ellipse. */
249
250#ifndef RETROFLAT_3D
251 /* Under 3D mode, we should never be drawing directly to the screen! */
252 if( NULL == target ) {
253 target = retroflat_screen_buffer();
254 }
255#endif /* !RETROFLAT_3D */
256
257 retroflat_px_lock( target );
258
259 do {
260 /* For the soft_lut, input numbers are * 1000... so 0.1 becomes 100. */
261 for( i = 100 ; 2 * MFIX_PI + 100 > i ; i += 100 ) {
262 i_prev = i - 100;
263
264 px_x1 =
265 /* Offset circle center by X. */
266 x + (w / 2) +
267 /* Get Cartesian coord by multiplying polar coord by radius. */
268 /* (Note that we convert to i *after* multiplication so the number
269 * is big enough that the precision no longer matters! */
270 mfix_to_i( mfix_cos( i_prev ) * w / 2 );
271
272 px_y1 = y + (h / 2) + mfix_to_i( mfix_sin( i_prev ) * (h / 2) );
273 px_x2 = x + (w / 2) + mfix_to_i( mfix_cos( i ) * (w / 2) );
274 px_y2 = y + (h / 2) + mfix_to_i( mfix_sin( i ) * (h / 2) );
275
276 /* We don't do bounds checks since the low-level API should handle
277 * those! Performance!
278 */
279
280 retrosoft_line( target, color, px_x1, px_y1, px_x2, px_y2, 0 );
281 }
282
283 /* Keep shrinking and filling if required. */
284 if( w > h ) {
285 x++;
286 w--;
287 if( 0 < h ) {
288 y++;
289 h--;
290 }
291 } else if( h > w ) {
292 y++;
293 h--;
294 if( 0 < w ) {
295 x++;
296 w--;
297 }
298 } else {
299 x++;
300 w--;
301 y++;
302 h--;
303 }
304 assert( 0 <= w );
305 assert( 0 <= h );
306 /* debug_printf( 1, "ELLIPSE %d, %d", w, h ); */
307 } while(
309 (0 < w || 0 < h)
310 );
311
312 retroflat_px_release( target );
313}
314
315#endif /* RETROSFT_C */
316
317#endif /* !RETROSFT_H */
318
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition retroflt.h:325
#define retroflat_2d_px(...)
Wrapper macro to call appropriate 2D surface blitter for pixels.
Definition retroflt.h:935
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition retroflt.h:373
void retroflat_line(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t flags)
Draw a straight line onto the target RETROFLAT_BITMAP.
void retrosoft_rect(retroflat_blit_t *target, const RETROFLAT_COLOR color_idx, int x, int y, int w, int h, uint8_t flags)
Draw a rectangle at the given coordinates, with the given dimensions.
void retrosoft_ellipse(retroflat_blit_t *target, RETROFLAT_COLOR color, int x, int y, int w, int h, uint8_t flags)
Draw an ellipsoid at the given coordinates, with the given dimensions.
void retrosoft_line(retroflat_blit_t *target, RETROFLAT_COLOR color, int x1, int y1, int x2, int y2, uint8_t flags)
Draw a line from x1, y1 to x2, y2.
#define retroflat_screen_buffer()
Get the direct screen buffer or the VDP buffer if a VDP is loaded.
Definition retpltd.h:41