maug
Quick and dirty C mini-augmentation library.
retrogxc.h
1
2#ifndef RETROGXC_H
3#define RETROGXC_H
4
12#include <maug.h>
13
14/* TODO: Unified asset type that automatically uses RetroGXC if present and
15 * directly loads assets to handles if not.
16 *
17 * *or*
18 *
19 * Loader function that passes back a pointer to the cached object
20 * to be used with the normal functions associated with it.
21 */
22
23/* TODO: The loaders here pass path to file-loading functions. What they
24 * *should* do is open those paths into mfiles on their own, so that
25 * a shim can be inserted to force loading from arrays in memory.
26 */
27
28#define RETROGXC_PRESENT 1
29
30#ifndef RETROGXC_INITIAL_SZ
31# define RETROGXC_INITIAL_SZ 16
32#endif /* !RETROGXC_INITIAL_SZ */
33
34#ifndef RETROGXC_TRACE_LVL
35# define RETROGXC_TRACE_LVL 0
36#endif /* !RETROGXC_TRACE_LVL */
37
38#define RETROGXC_ERROR_CACHE_MISS (-1)
39
40#define RETROGXC_ASSET_TYPE_NONE 0
41#define RETROGXC_ASSET_TYPE_BITMAP 1
42#define RETROGXC_ASSET_TYPE_FONT 2
43
44#define retrogxc_load_bitmap( res_p, flags ) \
45 retrogxc_load_asset( res_p, retrogxc_loader_bitmap, NULL, flags )
46
47typedef int8_t retrogxc_asset_type_t;
48
49typedef retrogxc_asset_type_t (*retrogxc_loader)(
50 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p,
51 void* data, uint8_t flags );
52
54 uint8_t type;
55 MAUG_MHANDLE handle;
57};
58
60 uint8_t glyph_h;
61 uint16_t first_glyph;
62 uint16_t glyphs_count;
63};
64
65MERROR_RETVAL retrogxc_init();
66
67void retrogxc_clear_cache();
68
69void retrogxc_shutdown();
70
71retrogxc_asset_type_t retrogxc_loader_bitmap(
72 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p,
73 void* data, uint8_t flags );
74
75retrogxc_asset_type_t retrogxc_loader_xpm(
76 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p,
77 void* data, uint8_t flags );
78
79retrogxc_asset_type_t retrogxc_loader_font(
80 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p,
81 void* data, uint8_t flags );
82
83int16_t retrogxc_load_font(
84 const retroflat_asset_path font_name,
85 uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count );
86
87int16_t retrogxc_load_asset(
88 const retroflat_asset_path res_p, retrogxc_loader l, void* data,
89 uint8_t flags );
90
91MERROR_RETVAL retrogxc_blit_bitmap(
92 retroflat_blit_t* target, size_t bitmap_idx,
93 size_t s_x, size_t s_y, size_t d_x, size_t d_y,
94 size_t w, size_t h, int16_t instance );
95
96MERROR_RETVAL retrogxc_string(
97 retroflat_blit_t* target, RETROFLAT_COLOR color,
98 const char* str, size_t str_sz,
99 size_t font_idx, size_t x, size_t y,
100 size_t max_w, size_t max_h, uint8_t flags );
101
102MERROR_RETVAL retrogxc_string_indent(
103 retroflat_blit_t* target, RETROFLAT_COLOR color,
104 const char* str, size_t str_sz,
105 size_t font_idx, size_t x, size_t y,
106 size_t max_w, size_t max_h, size_t indent, uint8_t flags );
107
108MERROR_RETVAL retrogxc_string_sz(
109 retroflat_blit_t* target, const char* str, size_t str_sz,
110 size_t font_idx, size_t max_w, size_t max_h,
111 size_t* out_w_p, size_t* out_h_p, uint8_t flags );
112
113MERROR_RETVAL retrogxc_bitmap_wh(
114 size_t bitmap_idx, retroflat_pxxy_t* p_w, retroflat_pxxy_t* p_h );
115
116#ifdef RETROGXC_C
117
118static struct MDATA_VECTOR SEG_MGLOBAL gs_retrogxc_bitmaps;
119
120/* === */
121
122MERROR_RETVAL retrogxc_init() {
123 MERROR_RETVAL retval = MERROR_OK;
124
125 /*
126 size_printf( RETROGXC_TRACE_LVL,
127 "asset struct", sizeof( struct RETROFLAT_CACHE_ASSET ) );
128 size_printf( RETROGXC_TRACE_LVL, "initial graphics cache",
129 sizeof( struct RETROFLAT_CACHE_ASSET ) * gs_retrogxc_sz );
130 */
131
132 return retval;
133}
134
135/* === */
136
137void retrogxc_clear_cache() {
138 size_t dropped_count = 0;
139 struct RETROFLAT_CACHE_ASSET* asset = NULL;
140 retroflat_blit_t* bitmap = NULL;
141 MERROR_RETVAL retval = MERROR_OK;
142
143 if( 0 == mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
144 /* Nothing to do! */
145 return;
146 }
147
148 mdata_vector_lock( &gs_retrogxc_bitmaps );
149
150 while( 0 < mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
151 asset = mdata_vector_get(
152 &gs_retrogxc_bitmaps, 0, struct RETROFLAT_CACHE_ASSET );
153 assert( NULL != asset );
154
155 /* Asset-type-specific cleanup. */
156 switch( asset->type ) {
157 case RETROGXC_ASSET_TYPE_BITMAP:
158 maug_mlock( asset->handle, bitmap );
159 if( NULL != bitmap ) {
160 retroflat_2d_destroy_bitmap( bitmap );
161 }
162 maug_munlock( asset->handle, bitmap );
163 maug_mfree( asset->handle );
164 dropped_count++;
165
166 case RETROGXC_ASSET_TYPE_FONT:
167 /* Fonts are just a blob of data after a struct, so just free it! */
168 retrofont_free( &(asset->handle) );
169 dropped_count++;
170 }
171
172 mdata_vector_unlock( &gs_retrogxc_bitmaps );
173 mdata_vector_remove( &gs_retrogxc_bitmaps, 0 );
174 mdata_vector_lock( &gs_retrogxc_bitmaps );
175 }
176
177 debug_printf( RETROGXC_TRACE_LVL,
178 "graphics cache cleared (" SIZE_T_FMT " assets)", dropped_count );
179
180cleanup:
181
182 if( MERROR_OK == retval ) {
183 mdata_vector_unlock( &gs_retrogxc_bitmaps );
184 }
185
186 return;
187}
188
189/* === */
190
191void retrogxc_shutdown() {
192 retrogxc_clear_cache();
193 mdata_vector_free( &gs_retrogxc_bitmaps );
194}
195
196/* === */
197
198retrogxc_asset_type_t retrogxc_loader_bitmap(
199 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p, void* data,
200 uint8_t flags
201) {
202 MERROR_RETVAL retval = MERROR_OK;
203 retroflat_blit_t* bitmap = NULL;
204
205 assert( (MAUG_MHANDLE)NULL == *handle_p );
206
207 *handle_p = maug_malloc( 1, sizeof( retroflat_blit_t ) );
208 maug_cleanup_if_null_alloc( MAUG_MHANDLE, *handle_p );
209
210 maug_mlock( *handle_p, bitmap );
211 maug_cleanup_if_null_alloc( retroflat_blit_t*, bitmap );
212
213 /* Load requested bitmap into the cache. */
214#ifdef RETROFLAT_XPM
215 retval = retroflat_load_xpm( res_p, bitmap, flags );
216#else
217 retval = retroflat_2d_load_bitmap( res_p, bitmap, flags );
218#endif /* RETROFLAT_XPM */
219 maug_cleanup_if_not_ok();
220
221cleanup:
222
223 if( NULL != bitmap ) {
224 maug_munlock( *handle_p, bitmap );
225 }
226
227 if( MERROR_OK == retval ) {
228 return RETROGXC_ASSET_TYPE_BITMAP;
229 } else {
230 if( (MAUG_MHANDLE)NULL != *handle_p ) {
231 maug_mfree( *handle_p );
232 }
233 return RETROGXC_ASSET_TYPE_NONE;
234 }
235}
236
237/* === */
238
239#ifdef RETROFONT_PRESENT
240
241retrogxc_asset_type_t retrogxc_loader_font(
242 const retroflat_asset_path res_p, MAUG_MHANDLE* handle_p, void* data,
243 uint8_t flags
244) {
245 MERROR_RETVAL retval = MERROR_OK;
246 struct RETROGXC_FONT_PARMS* parms = (struct RETROGXC_FONT_PARMS*)data;
247
248 assert( (MAUG_MHANDLE)NULL == *handle_p );
249
250 debug_printf( 1, "loading font into cache: %s (%d, %d, %d)",
251 res_p, parms->glyph_h, parms->first_glyph, parms->glyphs_count );
252
253 retval = retrofont_load( res_p, handle_p,
254 parms->glyph_h, parms->first_glyph, parms->glyphs_count );
255 maug_cleanup_if_not_ok();
256
257cleanup:
258
259 if( MERROR_OK == retval ) {
260 return RETROGXC_ASSET_TYPE_FONT;
261 } else {
262 return RETROGXC_ASSET_TYPE_NONE;
263 }
264}
265
266#endif /* RETROFONT_PRESENT */
267
268/* === */
269
270int16_t retrogxc_load_asset(
271 const retroflat_asset_path res_p, retrogxc_loader l, void* data,
272 uint8_t flags
273) {
274 int16_t idx = RETROGXC_ERROR_CACHE_MISS,
275 i = 0;
276 struct RETROFLAT_CACHE_ASSET asset_new;
277 struct RETROFLAT_CACHE_ASSET* asset_iter = NULL;
278 retrogxc_asset_type_t asset_type = RETROGXC_ASSET_TYPE_NONE;
279 MERROR_RETVAL retval = MERROR_OK;
280
281 maug_mzero( &asset_new, sizeof( struct RETROFLAT_CACHE_ASSET ) );
282
283 if( 0 == mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
284 goto just_load_asset;
285 }
286
287 /* Try to find the bitmap already in the cache. */
288 mdata_vector_lock( &gs_retrogxc_bitmaps );
289 for( i = 0 ; mdata_vector_ct( &gs_retrogxc_bitmaps ) > (size_t)i ; i++ ) {
290 asset_iter = mdata_vector_get(
291 &gs_retrogxc_bitmaps, i, struct RETROFLAT_CACHE_ASSET );
292 assert( NULL != asset_iter );
293 debug_printf( RETROGXC_TRACE_LVL, "\"%s\" vs \"%s\"",
294 asset_iter->id, res_p );
295 if( 0 == mfile_cmp_path( asset_iter->id, res_p ) ) {
296 debug_printf( RETROGXC_TRACE_LVL,
297 "found asset \"%s\" at index %d with type %d!",
298 res_p, i, asset_iter->type );
299 idx = i;
300 mdata_vector_unlock( &gs_retrogxc_bitmaps );
301 goto cleanup;
302 }
303 }
304 mdata_vector_unlock( &gs_retrogxc_bitmaps );
305
306just_load_asset:
307
308 /* Bitmap not found. */
309 debug_printf( RETROGXC_TRACE_LVL,
310 "asset %s not found in cache; loading...", res_p );
311
312 /* Call the format-specific loader. */
313 asset_type = l( res_p, &asset_new.handle, data, flags );
314 if( RETROGXC_ASSET_TYPE_NONE != asset_type ) {
315 asset_new.type = asset_type;
316 mfile_assign_path( asset_new.id, res_p, 0 );
318 &gs_retrogxc_bitmaps, &asset_new,
319 sizeof( struct RETROFLAT_CACHE_ASSET ) );
320 if( 0 > idx ) {
321 goto cleanup;
322 }
323 debug_printf( RETROGXC_TRACE_LVL,
324 "asset type %d, \"%s\" assigned cache ID: %d",
325 asset_type, res_p, idx );
326 goto cleanup;
327 }
328
329 /* Still not found! */
330 error_printf( "unable to load asset; cache full or not initialized?" );
331
332cleanup:
333
334 if( MERROR_OK != retval ) {
335 idx = retval * -1;
336 }
337
338 return idx;
339}
340
341/* === */
342
343MERROR_RETVAL retrogxc_blit_bitmap(
344 retroflat_blit_t* target, size_t bitmap_idx,
345 size_t s_x, size_t s_y, size_t d_x, size_t d_y,
346 size_t w, size_t h, int16_t instance
347) {
348 MERROR_RETVAL retval = MERROR_OK;
349 struct RETROFLAT_CACHE_ASSET* asset = NULL;
350 retroflat_blit_t* bitmap = NULL;
351
352 assert( (MAUG_MHANDLE)NULL != gs_retrogxc_bitmaps.data_h );
353
354 mdata_vector_lock( &gs_retrogxc_bitmaps );
355
356 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= bitmap_idx ) {
357 error_printf( "invalid bitmap index: " SIZE_T_FMT, bitmap_idx );
358 retval = MERROR_OVERFLOW;
359 goto cleanup;
360 }
361
362 asset = mdata_vector_get(
363 &gs_retrogxc_bitmaps, bitmap_idx, struct RETROFLAT_CACHE_ASSET );
364
365 if( RETROGXC_ASSET_TYPE_BITMAP != asset->type ) {
366 error_printf(
367 "index " SIZE_T_FMT " not present in cache or not bitmap (%d)!",
368 bitmap_idx, asset->type );
369 retval = MERROR_FILE;
370 goto cleanup;
371 }
372
373 maug_mlock( asset->handle, bitmap );
374
375 retval = retroflat_2d_blit_bitmap(
376 target, bitmap, s_x, s_y, d_x, d_y, w, h, instance );
377
378cleanup:
379
380 if( NULL != bitmap ) {
381 maug_munlock( asset->handle, bitmap );
382 }
383
384 mdata_vector_unlock( &gs_retrogxc_bitmaps );
385
386 return retval;
387}
388
389/* === */
390
391MERROR_RETVAL retrogxc_bitmap_wh(
392 size_t bitmap_idx, retroflat_pxxy_t* p_w, retroflat_pxxy_t* p_h
393) {
394 MERROR_RETVAL retval = MERROR_OK;
395 struct RETROFLAT_CACHE_ASSET* asset = NULL;
396 retroflat_blit_t* bitmap = NULL;
397
398 mdata_vector_lock( &gs_retrogxc_bitmaps );
399
400 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= bitmap_idx ) {
401 error_printf( "invalid bitmap index: " SIZE_T_FMT, bitmap_idx );
402 retval = MERROR_OVERFLOW;
403 goto cleanup;
404 }
405
406 asset = mdata_vector_get(
407 &gs_retrogxc_bitmaps, bitmap_idx, struct RETROFLAT_CACHE_ASSET );
408
409 if( RETROGXC_ASSET_TYPE_BITMAP != asset->type ) {
410 error_printf(
411 "index " SIZE_T_FMT " not present in cache or not bitmap (%d)!",
412 bitmap_idx, asset->type );
413 retval = MERROR_FILE;
414 goto cleanup;
415 }
416
417 maug_mlock( asset->handle, bitmap );
418
419 if( NULL != p_w ) {
420 *p_w = retroflat_2d_bitmap_w( bitmap );
421 }
422
423 if( NULL != p_h ) {
424 *p_h = retroflat_2d_bitmap_h( bitmap );
425 }
426
427cleanup:
428
429 if( NULL != bitmap ) {
430 maug_munlock( asset->handle, bitmap );
431 }
432
433 mdata_vector_unlock( &gs_retrogxc_bitmaps );
434
435 return retval;
436}
437
438/* === */
439
440#ifdef RETROFONT_PRESENT
441
442int16_t retrogxc_load_font(
443 const retroflat_asset_path font_name,
444 uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count
445) {
446 int16_t idx = -1;
447 struct RETROGXC_FONT_PARMS parms;
448
449 parms.glyph_h = glyph_h;
450 parms.first_glyph = first_glyph;
451 parms.glyphs_count = glyphs_count;
452
453 idx = retrogxc_load_asset( font_name, retrogxc_loader_font, &parms, 0 );
454
455 return idx;
456}
457
458/* === */
459
460MERROR_RETVAL retrogxc_string(
461 retroflat_blit_t* target, RETROFLAT_COLOR color,
462 const char* str, size_t str_sz,
463 size_t font_idx, size_t x, size_t y,
464 size_t max_w, size_t max_h, uint8_t flags
465) {
466
467 return retrogxc_string_indent(
468 target, color, str, str_sz, font_idx, x, y, max_w, max_h, 0, flags );
469}
470
471/* === */
472
473MERROR_RETVAL retrogxc_string_indent(
474 retroflat_blit_t* target, RETROFLAT_COLOR color,
475 const char* str, size_t str_sz,
476 size_t font_idx, size_t x, size_t y,
477 size_t max_w, size_t max_h, size_t indent, uint8_t flags
478) {
479 MERROR_RETVAL retval = MERROR_OK;
480 struct RETROFLAT_CACHE_ASSET* asset = NULL;
481
482 mdata_vector_lock( &gs_retrogxc_bitmaps );
483
484 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= font_idx ) {
485 error_printf( "invalid font index: " SIZE_T_FMT, font_idx );
486 retval = MERROR_OVERFLOW;
487 goto cleanup;
488 }
489
490 asset = mdata_vector_get(
491 &gs_retrogxc_bitmaps, font_idx, struct RETROFLAT_CACHE_ASSET );
492
493 if( RETROGXC_ASSET_TYPE_FONT != asset->type ) {
494 error_printf(
495 "index " SIZE_T_FMT " not present in cache or not font (%d)!",
496 font_idx, asset->type );
497 retval = MERROR_FILE;
498 goto cleanup;
499 }
500
501 retrofont_string_indent(
502 target, color, str, str_sz, asset->handle, x, y, max_w, max_h,
503 indent, flags );
504
505cleanup:
506
507 mdata_vector_unlock( &gs_retrogxc_bitmaps );
508
509 return retval;
510}
511
512/* === */
513
514MERROR_RETVAL retrogxc_string_sz(
515 retroflat_blit_t* target, const char* str, size_t str_sz,
516 size_t font_idx, size_t max_w, size_t max_h,
517 size_t* out_w_p, size_t* out_h_p, uint8_t flags
518) {
519 MERROR_RETVAL retval = MERROR_OK;
520 struct RETROFLAT_CACHE_ASSET* asset = NULL;
521
522 mdata_vector_lock( &gs_retrogxc_bitmaps );
523
524 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= font_idx ) {
525 error_printf( "invalid font index: " SIZE_T_FMT, font_idx );
526 retval = MERROR_OVERFLOW;
527 goto cleanup;
528 }
529
530 asset = mdata_vector_get(
531 &gs_retrogxc_bitmaps, font_idx, struct RETROFLAT_CACHE_ASSET );
532
533 if( RETROGXC_ASSET_TYPE_FONT != asset->type ) {
534 error_printf(
535 "index " SIZE_T_FMT " not present in cache or not font (%d)!",
536 font_idx, asset->type );
537 retval = MERROR_FILE;
538 goto cleanup;
539 }
540
541 retrofont_string_sz(
542 target, str, str_sz, asset->handle,
543 max_w, max_h, out_w_p, out_h_p, flags );
544
545cleanup:
546
547 mdata_vector_unlock( &gs_retrogxc_bitmaps );
548
549 return retval;
550}
551
552#endif /* RETROFONT_PRESENT */
553
554#endif /* RETROGXC_C */
555 /* maug_retroflt */
557 /* maug_retrogxc */
559
560#endif /* !RETROGXC_H */
561
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:19
char retroflat_asset_path[MAUG_PATH_SZ_MAX+1]
Path/name used to load an asset from disk.
Definition: mfile.h:129
#define mfile_cmp_path(a, b)
Compare two asset paths. Return 0 if they're the same.
Definition: mfile.h:134
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition: retroflt.h:325
size_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:870
ssize_t mdata_vector_append(struct MDATA_VECTOR *v, const void *item, size_t item_sz)
Append an item to the specified vector.
MERROR_RETVAL mdata_vector_remove(struct MDATA_VECTOR *v, size_t idx)
Remove item at the given index, shifting subsequent items up by 1.
MERROR_RETVAL retrofont_load(const char *font_name, MAUG_MHANDLE *p_font_h, uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count)
Load a font for drawing.
A vector of uniformly-sized objects, stored contiguously.
Definition: mdata.h:93
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:320
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:353
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:396
Definition: retrogxc.h:53
Definition: retrogxc.h:59