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