maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
retrosft.h
1
2#ifndef RETROSFT_H
3#define RETROSFT_H
4
5#define RETROFLAT_LINE_X 0
6#define RETROFLAT_LINE_Y 1
7
8#ifndef RETROSOFT_TRACE_LVL
9# define RETROSOFT_TRACE_LVL 0
10#endif /* RETROSOFT_TRACE_LVL */
11
12MERROR_RETVAL retrosoft_load_glyph(
13 RETROFLAT_COLOR color,
14 size_t set_idx, size_t glyph_idx, struct RETROFLAT_BITMAP* bmp );
15
16MERROR_RETVAL retrosoft_init();
17
18void retrosoft_shutdown();
19
20void retrosoft_line(
21 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
22 int x1, int y1, int x2, int y2, uint8_t flags );
23
24void retrosoft_rect(
25 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color_idx,
26 int x, int y, int w, int h, uint8_t flags );
27
28void retrosoft_ellipse(
29 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
30 int x, int y, int w, int h, uint8_t flags );
31
32void retrosoft_ellipse(
33 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
34 int x, int y, int w, int h, uint8_t flags );
35
36void retrosoft_string_sz(
37 struct RETROFLAT_BITMAP* target, const char* str, size_t str_sz,
38 const char* font_str, size_t* w_out, size_t* h_out, uint8_t flags );
39
40void retrosoft_string(
41 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
42 const char* str, size_t str_sz, const char* font_str, int x_orig, int y_orig,
43 uint8_t flags );
44
45#ifdef RETROSFT_C
46
47# include "mfont8x8.h"
48
49# ifndef RETROFLAT_NO_STRING
50/* TODO: Create another depth for each color. */
51static struct RETROFLAT_BITMAP
52gc_font_bmps[RETROFLAT_COLORS_SZ][RETROSOFT_SETS_COUNT][RETROSOFT_GLYPHS_COUNT];
53# endif /* !RETROFLAT_NO_STRING */
54
55/* === */
56
57# ifndef RETROFLAT_NO_STRING
58
59MERROR_RETVAL retrosoft_load_glyph(
60 RETROFLAT_COLOR color,
61 size_t set_idx, size_t glyph_idx, struct RETROFLAT_BITMAP* bmp
62) {
63 MERROR_RETVAL retval = MERROR_OK;
64 int x = 0,
65 y = 0;
66 const char* glyph_dots = gc_font8x8[set_idx][glyph_idx];
67
68 /* Create a transparent bitmap to draw on. */
69 retval = retroflat_create_bitmap(
70 RETROSOFT_GLYPH_W_SZ, RETROSOFT_GLYPH_H_SZ, bmp, 0 );
71 maug_cleanup_if_not_ok();
72
73 /* Normally draw lock is called from the main loop, but we're making an
74 * off-screen bitmap, here!
75 */
77 retroflat_px_lock( bmp );
78
79 /* Draw the glyph onto the bitmap. */
80 for( y = 0 ; RETROSOFT_GLYPH_H_SZ > y ; y++ ) {
81 for( x = 0 ; RETROSOFT_GLYPH_W_SZ > x ; x++ ) {
82 if( 1 == ((glyph_dots[y] >> x) & 0x01) ) {
83 retroflat_px( bmp, color, x, y, 0 );
84 }
85 }
86 }
87
88 retroflat_px_release( bmp );
89 retroflat_draw_release( bmp );
90
91 /*
92 retroflat_rect(
93 bmp, RETROFLAT_COLOR_RED, 0, 0,
94 RETROSOFT_GLYPH_W_SZ, RETROSOFT_GLYPH_H_SZ, RETROFLAT_FLAGS_FILL );
95 */
96
97cleanup:
98
99 return retval;
100}
101
102# endif /* !RETROFLAT_NO_STRING */
103
104/* === */
105
106MERROR_RETVAL retrosoft_init() {
107 MERROR_RETVAL retval = MERROR_OK;
108# ifndef RETROFLAT_NO_STRING
109 size_t i = 0,
110 j = 0;
111 RETROFLAT_COLOR h = RETROFLAT_COLOR_WHITE;
112
113# ifdef RETROSOFT_PRELOAD_COLORS
114 for( h = 0 ; RETROFLAT_COLORS_SZ > h ; h++ ) {
115 debug_printf( RETROSOFT_TRACE_LVL,
116 "loading glyphs in %s...", gc_retroflat_color_names[h] );
117# endif /* RETROSOFT_PRELOAD_COLORS */
118 for( i = 0 ; RETROSOFT_SETS_COUNT > i ; i++ ) {
119 for( j = 0 ; RETROSOFT_GLYPHS_COUNT > j ; j++ ) {
120 debug_printf( RETROSOFT_TRACE_LVL,
121 "loading glyph " SIZE_T_FMT "...", j );
122 retval = retrosoft_load_glyph( h, i, j, &(gc_font_bmps[h][i][j]) );
123 maug_cleanup_if_not_ok();
124 }
125 }
126# ifdef RETROSOFT_PRELOAD_COLORS
127 }
128# endif /* RETROSOFT_PRELOAD_COLORS */
129
130cleanup:
131
132# endif /* !RETROFLAT_NO_STRING */
133
134 /* TODO: Unload loaded bitmaps if retval not OK. */
135
136 return retval;
137}
138
139/* === */
140
141void retrosoft_shutdown() {
142# ifndef RETROFLAT_NO_STRING
143 size_t i = 0,
144 j = 0;
145 RETROFLAT_COLOR h = RETROFLAT_COLOR_WHITE;
146# endif /* !RETROFLAT_NO_STRING */
147
148 debug_printf( RETROSOFT_TRACE_LVL, "retrosoft shutdown called..." );
149
150# ifndef RETROFLAT_NO_STRING
151
152#ifdef RETROSOFT_PRELOAD_COLORS
153 for( h = 0 ; RETROFLAT_COLORS_SZ > h ; h++ ) {
154#endif /* RETROSOFT_PRELOAD_COLORS */
155 for( i = 0 ; RETROSOFT_SETS_COUNT > i ; i++ ) {
156 for( j = 0 ; RETROSOFT_GLYPHS_COUNT > j ; j++ ) {
157 debug_printf( RETROSOFT_TRACE_LVL,
158 "destroying glyph " SIZE_T_FMT "...", j );
159 retroflat_destroy_bitmap( &(gc_font_bmps[h][i][j]) );
160 }
161 }
162#ifdef RETROSOFT_PRELOAD_COLORS
163 }
164#endif /* RETROSOFT_PRELOAD_COLORS */
165
166# endif /* !RETROFLAT_NO_STRING */
167}
168
169/* === */
170
171void retrosoft_line_strategy(
172 int x1, int y1, int x2, int y2,
173 uint8_t* p_for_axis, uint8_t* p_off_axis, int16_t dist[2],
174 int16_t start[2], int16_t end[2], int16_t iter[2],
175 int16_t* p_inc, int16_t* p_delta
176) {
177
178 /* Figure out strategy based on line slope. */
179 if( abs( y2 - y1 ) < abs( x2 - x1 ) ) {
180 if( x1 > x2 ) {
181 start[RETROFLAT_LINE_X] = x2;
182 start[RETROFLAT_LINE_Y] = y2;
183 end[RETROFLAT_LINE_X] = x1;
184 end[RETROFLAT_LINE_Y] = y1;
185 *p_for_axis = RETROFLAT_LINE_X;
186 } else {
187 start[RETROFLAT_LINE_X] = x1;
188 start[RETROFLAT_LINE_Y] = y1;
189 end[RETROFLAT_LINE_X] = x2;
190 end[RETROFLAT_LINE_Y] = y2;
191 *p_for_axis = RETROFLAT_LINE_X;
192 }
193 } else {
194 if( y2 < y1 ) {
195 start[RETROFLAT_LINE_X] = x2;
196 start[RETROFLAT_LINE_Y] = y2;
197 end[RETROFLAT_LINE_X] = x1;
198 end[RETROFLAT_LINE_Y] = y1;
199 *p_for_axis = RETROFLAT_LINE_Y;
200 } else {
201 start[RETROFLAT_LINE_X] = x1;
202 start[RETROFLAT_LINE_Y] = y1;
203 end[RETROFLAT_LINE_X] = x2;
204 end[RETROFLAT_LINE_Y] = y2;
205 *p_for_axis = RETROFLAT_LINE_Y;
206 }
207 }
208
209 /* C89 requires const initializers, so do math down here. */
210 *p_off_axis = 1 - *p_for_axis;
211 iter[RETROFLAT_LINE_X] = start[RETROFLAT_LINE_X];
212 iter[RETROFLAT_LINE_Y] = start[RETROFLAT_LINE_Y];
213 dist[RETROFLAT_LINE_X] = end[RETROFLAT_LINE_X] - start[RETROFLAT_LINE_X];
214 dist[RETROFLAT_LINE_Y] = end[RETROFLAT_LINE_Y] - start[RETROFLAT_LINE_Y];
215
216 /* Adjust delta/slope for off-axis. */
217 *p_delta = (2 * dist[*p_off_axis]) - dist[*p_for_axis];
218 if( 0 > dist[*p_off_axis] ) {
219 *p_inc = -1;
220 dist[*p_off_axis] *= -1;
221 } else {
222 *p_inc = 1;
223 }
224
225
226}
227
228#if defined( RETROFLAT_OPENGL ) || \
229 defined( RETROFLAT_API_PC_BIOS ) || \
230 defined( RETROFLAT_SOFT_LINES )
231
232void retrosoft_line(
233 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
234 int x1, int y1, int x2, int y2, uint8_t flags
235) {
236
237 uint8_t for_axis = 0,
238 off_axis = 0;
239 int16_t dist[2],
240 start[2],
241 end[2],
242 iter[2],
243 inc = 1,
244 delta = 0;
245
246 /* TODO: Handle thickness. */
247
248 if( NULL == target ) {
249 target = retroflat_screen_buffer();
250 }
251
252 retroflat_px_lock( target );
253
254 retrosoft_line_strategy(
255 x1, y1, x2, y2,
256 &for_axis, &off_axis, dist, start, end, iter, &inc, &delta );
257
258 for(
259 iter[for_axis] = start[for_axis] ;
260 end[for_axis] > iter[for_axis] ;
261 iter[for_axis]++
262 ) {
263
264 /*
265 if(
266 (size_t)iter[RETROFLAT_LINE_X] < (size_t)retroflat_screen_w() &&
267 (size_t)iter[RETROFLAT_LINE_Y] < (size_t)retroflat_screen_h()
268 ) {
269 */
270 retroflat_px(
271 target, color,
272 iter[RETROFLAT_LINE_X], iter[RETROFLAT_LINE_Y], 0 );
273 /* } */
274
275 /* Increment off-axis based on for-axis. */
276 if( 0 < delta ) {
277 iter[off_axis] += inc;
278 delta += (2 * (dist[off_axis] - dist[for_axis]));
279 } else {
280 delta += (2 * dist[off_axis]);
281 }
282 }
283
284 retroflat_px_release( target );
285}
286
287#endif /* RETROFLAT_OPENGL || RETROFLAT_SOFT_LINES */
288
289/* === */
290
291void retrosoft_rect(
292 struct RETROFLAT_BITMAP* target, const RETROFLAT_COLOR color_idx,
293 int x, int y, int w, int h, uint8_t flags
294) {
295 int x_iter = 0,
296 y_iter = 0;
297
298 if( NULL == target ) {
299 target = retroflat_screen_buffer();
300 }
301
302 retroflat_px_lock( target );
303
305
306 for( y_iter = y ; y_iter < y + h ; y_iter++ ) {
307 for( x_iter = x ; x_iter < x + w ; x_iter++ ) {
308 /* TODO: Optimize filling 4-byte sequences! */
309 retroflat_px( target, color_idx, x_iter, y_iter, 0 );
310 }
311 }
312
313 } else {
314
315#ifdef RETROFLAT_SOFT_LINES
316 retrosoft_line( target, color_idx, x, y, x + w, y, 0 );
317 retrosoft_line( target, color_idx, x + w, y, x + w, y + h, 0 );
318 retrosoft_line( target, color_idx, x + w, y + h, x, y + h, 0 );
319 retrosoft_line( target, color_idx, x, y + h, x, y, 0 );
320#else
321 retroflat_line( target, color_idx, x, y, x + w, y, 0 );
322 retroflat_line( target, color_idx, x + w, y, x + w, y + h, 0 );
323 retroflat_line( target, color_idx, x + w, y + h, x, y + h, 0 );
324 retroflat_line( target, color_idx, x, y + h, x, y, 0 );
325#endif
326
327 }
328
329 retroflat_px_release( target );
330}
331
332/* === */
333
334void retrosoft_ellipse(
335 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
336 int x, int y, int w, int h, uint8_t flags
337) {
338 int32_t i = 0,
339 i_prev = 0;
340 uint16_t px_x1 = 0,
341 px_y1 = 0,
342 px_x2 = 0,
343 px_y2 = 0;
344
345 /* TODO: Switch to Bresenham algorithm. */
346
347 /* TODO: Filled ellipse. */
348
349 if( NULL == target ) {
350 target = retroflat_screen_buffer();
351 }
352
353 retroflat_px_lock( target );
354
355 do {
356 /* For the soft_lut, input numbers are * 1000... so 0.1 becomes 100. */
357 for( i = 100 ; 2 * RETROFP_PI + 100 > i ; i += 100 ) {
358 i_prev = i - 100;
359
360 px_x1 = x + (w / 2) + retrofp_cos( i_prev, w / 2 );
361 px_y1 = y + (h / 2) + retrofp_sin( i_prev, h / 2 );
362 px_x2 = x + (w / 2) + retrofp_cos( i, w / 2 );
363 px_y2 = y + (h / 2) + retrofp_sin( i, h / 2 );
364
365 /*
366 if(
367 retroflat_bitmap_w( target ) <= px_x1 ||
368 retroflat_bitmap_h( target ) <= px_y1 ||
369 retroflat_bitmap_w( target ) <= px_x2 ||
370 retroflat_bitmap_h( target ) <= px_y2
371 ) {
372 continue;
373 }
374 */
375
376 retroflat_line( target, color, px_x1, px_y1, px_x2, px_y2, 0 );
377 }
378
379 /* Keep shrinking and filling if required. */
380 if( w > h ) {
381 x++;
382 w--;
383 if( 0 < h ) {
384 y++;
385 h--;
386 }
387 } else if( h > w ) {
388 y++;
389 h--;
390 if( 0 < w ) {
391 x++;
392 w--;
393 }
394 } else {
395 x++;
396 w--;
397 y++;
398 h--;
399 }
400 assert( 0 <= w );
401 assert( 0 <= h );
402 /* debug_printf( 1, "ELLIPSE %d, %d", w, h ); */
403 } while(
405 (0 < w || 0 < h)
406 );
407
408 retroflat_px_release( target );
409}
410
411# ifndef RETROFLAT_NO_STRING
412
413/* === */
414
415void retrosoft_string_sz(
416 struct RETROFLAT_BITMAP* target, const char* str, size_t str_sz,
417 const char* font_str, size_t* w_out, size_t* h_out, uint8_t flags
418) {
419 /* TODO: Put a little more effort into sizing. */
420 if( 0 == str_sz ) {
421 str_sz = maug_strlen( str );
422 }
423
424 *w_out = RETROSOFT_GLYPH_W_SZ * str_sz;
425 *h_out = RETROSOFT_GLYPH_H_SZ;
426}
427
428/* === */
429
430void retrosoft_string(
431 struct RETROFLAT_BITMAP* target, RETROFLAT_COLOR color,
432 const char* str, size_t str_sz, const char* font_str, int x_orig, int y_orig,
433 uint8_t flags
434) {
435 size_t i = 0,
436 glyph_idx = 0;
437 int x = x_orig;
438
439 if( 0 == str_sz ) {
440 str_sz = maug_strlen( str );
441 }
442
443 for( i = 0 ; str_sz > i ; i++ ) {
444 /* Terminate prematurely at null. */
445 if( '\0' == str[i] ) {
446 break;
447 }
448
449 /* Fonts start at character after space. */
450 glyph_idx = str[i] - ' ';
451
452#if defined( RETROFLAT_API_SDL2 ) && !defined( RETROSOFT_PRELOAD_COLORS )
453 /* If we're not caching the colors, use SDL2 features if available to
454 * tint the glyph before blitting it. */
455 SDL_SetSurfaceColorMod(
456 gc_font_bmps[RETROFLAT_COLOR_WHITE][0][glyph_idx].surface,
457 g_retroflat_state->palette[color].r,
458 g_retroflat_state->palette[color].g,
459 g_retroflat_state->palette[color].b );
460 SDL_DestroyTexture(
461 gc_font_bmps[RETROFLAT_COLOR_WHITE][0][glyph_idx].texture );
462 gc_font_bmps[RETROFLAT_COLOR_WHITE][0][glyph_idx].texture =
463 SDL_CreateTextureFromSurface(
464 g_retroflat_state->buffer.renderer,
465 gc_font_bmps[RETROFLAT_COLOR_WHITE][0][glyph_idx].surface );
466#endif /* RETROFLAT_API_SDL2 && !RETROSOFT_PRELOAD_COLORS */
467
469 target, &(gc_font_bmps[
470#ifdef RETROSOFT_PRELOAD_COLORS
471 color
472#else
473 RETROFLAT_COLOR_WHITE
474#endif /* !RETROSOFT_PRELOAD_COLORS */
475 ][0][glyph_idx]), 0, 0, x, y_orig,
476 RETROSOFT_GLYPH_W_SZ, RETROSOFT_GLYPH_H_SZ, RETROFLAT_INSTANCE_NULL );
477
478 x += 8;
479 }
480}
481
482# endif /* !RETROFLAT_NO_STRING */
483
484#else
485
486#endif /* RETROSFT_C */
487
488#endif /* !RETROSFT_H */
489
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
MERROR_RETVAL retroflat_blit_bitmap(struct RETROFLAT_BITMAP *target, struct RETROFLAT_BITMAP *src, size_t s_x, size_t s_y, int16_t d_x, int16_t d_y, size_t w, size_t h, int16_t instance)
Blit the contents of a RETROFLAT_BITMAP onto another RETROFLAT_BITMAP.
void retroflat_destroy_bitmap(struct RETROFLAT_BITMAP *bitmap)
Unload a bitmap from a RETROFLAT_BITMAP struct. The struct, itself, is not freed (in case it is on th...
#define RETROFLAT_INSTANCE_NULL
Pass to retroflat_blit_bitmap() instance arg if this is not a sprite (i.e. if it is a background tile...
Definition retroflt.h:567
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition retroflt.h:307
MERROR_RETVAL retroflat_draw_lock(struct RETROFLAT_BITMAP *bmp)
Lock a bitmap for drawing. This will be done automatically if necessary and not called explicitly,...
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition retroflt.h:355
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.
#define RETROFP_PI
Fixed-point representation of Pi (3.141).
Definition retrofp.h:17
#define retroflat_screen_buffer()
Get the direct screen buffer or the VDP buffer if a VDP is loaded.
Definition retpltd.h:41
Platform-specific bitmap structure. retroflat_bitmap_ok() can be used on a pointer to it to determine...
Definition retpltd.h:21
uint8_t flags
Platform-specific bitmap flags.
Definition retpltd.h:25
struct RETROFLAT_BITMAP buffer
Off-screen buffer bitmap.
Definition retroflt.h:1272
RETROFLAT_COLOR_DEF palette[RETROFLAT_COLORS_SZ]
Index of available colors, initialized on platform init.
Definition retroflt.h:1270