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