maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
retrogxc.h
1
2#ifndef RETROGXC_H
3#define RETROGXC_H
4
11
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#undef retrogxc_cachable_is_loaded
31#define retrogxc_cachable_is_loaded( cachable ) \
32 (0 <= (cachable)->cache_idx)
33
34#ifndef RETROGXC_INITIAL_SZ
35# define RETROGXC_INITIAL_SZ 16
36#endif /* !RETROGXC_INITIAL_SZ */
37
38#ifndef RETROGXC_TRACE_LVL
39# define RETROGXC_TRACE_LVL 0
40#endif /* !RETROGXC_TRACE_LVL */
41
42#define RETROGXC_ERROR_CACHE_MISS (-1)
43
44#define RETROGXC_ASSET_TYPE_NONE 0
45#define RETROGXC_ASSET_TYPE_BITMAP 1
46#define RETROGXC_ASSET_TYPE_FONT 2
47
48#define retrogxc_load_bitmap( res_p, flags ) \
49 retrogxc_load_asset( res_p, retrogxc_loader_bitmap, NULL, flags )
50
51typedef int8_t retrogxc_asset_type_t;
52
53typedef retrogxc_asset_type_t (*retrogxc_loader)(
54 const maug_path res_p, MAUG_MHANDLE* handle_p,
55 void* data, uint8_t flags );
56
58 uint8_t type;
59 MAUG_MHANDLE handle;
60 maug_path id;
61};
62
64 uint8_t glyph_h;
65 uint16_t first_glyph;
66 uint16_t glyphs_count;
67};
68
69MERROR_RETVAL retrogxc_init();
70
71void retrogxc_clear_cache();
72
73void retrogxc_shutdown();
74
75retrogxc_asset_type_t retrogxc_loader_bitmap(
76 const maug_path res_p, MAUG_MHANDLE* handle_p,
77 void* data, uint8_t flags );
78
79retrogxc_asset_type_t retrogxc_loader_xpm(
80 const maug_path res_p, MAUG_MHANDLE* handle_p,
81 void* data, uint8_t flags );
82
83retrogxc_asset_type_t retrogxc_loader_font(
84 const maug_path res_p, MAUG_MHANDLE* handle_p,
85 void* data, uint8_t flags );
86
87int16_t retrogxc_load_font(
88 const maug_path font_name,
89 uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count );
90
96 const maug_path res_p, retrogxc_loader l, void* data,
97 uint8_t flags );
98
106 size_t asset_idx, retrogxc_asset_type_t asset_type );
107
108MERROR_RETVAL retrogxc_blit_bitmap(
109 retroflat_blit_t* target, size_t bitmap_idx,
112 retroflat_pxxy_t w, retroflat_pxxy_t h, int16_t instance );
113
114MERROR_RETVAL retrogxc_bitmap_wh(
115 size_t bitmap_idx, retroflat_pxxy_t* p_w, retroflat_pxxy_t* p_h );
116
117#ifdef RETROGXC_C
118
119static struct MDATA_VECTOR SEG_MGLOBAL gs_retrogxc_bitmaps;
120
121/* === */
122
123MERROR_RETVAL retrogxc_init() {
124 MERROR_RETVAL retval = MERROR_OK;
125
126 /*
127 size_printf( RETROGXC_TRACE_LVL,
128 "asset struct", sizeof( struct RETROFLAT_CACHE_ASSET ) );
129 size_printf( RETROGXC_TRACE_LVL, "initial graphics cache",
130 sizeof( struct RETROFLAT_CACHE_ASSET ) * gs_retrogxc_sz );
131 */
132
133 g_retroflat_state->retroflat_flags |= RETROFLAT_FLAGS_USE_GXC;
134
135 return retval;
136}
137
138/* === */
139
140void retrogxc_clear_cache() {
141 size_t dropped_count = 0;
142 struct RETROFLAT_CACHE_ASSET* asset = NULL;
143 retroflat_blit_t* bitmap = NULL;
144 MERROR_RETVAL retval = MERROR_OK;
145
146 if( 0 == mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
147 /* Nothing to do! */
148 return;
149 }
150
151 mdata_vector_lock( &gs_retrogxc_bitmaps );
152
153 while( 0 < mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
154 asset = mdata_vector_get(
155 &gs_retrogxc_bitmaps, 0, struct RETROFLAT_CACHE_ASSET );
156 assert( NULL != asset );
157
158 /* Asset-type-specific cleanup. */
159 switch( asset->type ) {
160 case RETROGXC_ASSET_TYPE_BITMAP:
161 maug_mlock( asset->handle, bitmap );
162 if( NULL != bitmap ) {
163 retroflat_2d_destroy_bitmap( bitmap );
164 }
165 maug_munlock( asset->handle, bitmap );
166 maug_mfree( asset->handle );
167 dropped_count++;
168
169 case RETROGXC_ASSET_TYPE_FONT:
170 /* Fonts are just a blob of data after a struct, so just free it! */
171 retrofont_free( &(asset->handle) );
172 dropped_count++;
173 }
174
175 mdata_vector_unlock( &gs_retrogxc_bitmaps );
176 mdata_vector_remove( &gs_retrogxc_bitmaps, 0 );
177 mdata_vector_lock( &gs_retrogxc_bitmaps );
178 }
179
180 debug_printf( RETROGXC_TRACE_LVL,
181 "graphics cache cleared (" SIZE_T_FMT " assets)", dropped_count );
182
183cleanup:
184
185 if( MERROR_OK == retval ) {
186 mdata_vector_unlock( &gs_retrogxc_bitmaps );
187 }
188
189 return;
190}
191
192/* === */
193
194void retrogxc_shutdown() {
195 retrogxc_clear_cache();
196 mdata_vector_free( &gs_retrogxc_bitmaps );
197 g_retroflat_state->retroflat_flags &= ~RETROFLAT_FLAGS_USE_GXC;
198}
199
200/* === */
201
202retrogxc_asset_type_t retrogxc_loader_bitmap(
203 const maug_path res_p, MAUG_MHANDLE* handle_p, void* data,
204 uint8_t flags
205) {
206 MERROR_RETVAL retval = MERROR_OK;
207 retroflat_blit_t* bitmap = NULL;
208
209 assert( (MAUG_MHANDLE)NULL == *handle_p );
210
211 maug_malloc_test( *handle_p, 1, sizeof( retroflat_blit_t ) );
212
213 maug_mlock( *handle_p, bitmap );
214 maug_cleanup_if_null_alloc( retroflat_blit_t*, bitmap );
215
216 /* Load requested bitmap into the cache. */
217#ifdef RETROFLAT_XPM
218 retval = retroflat_load_xpm( res_p, bitmap, flags );
219#else
220 retval = retroflat_2d_load_bitmap( res_p, bitmap, flags );
221#endif /* RETROFLAT_XPM */
222 maug_cleanup_if_not_ok();
223
224cleanup:
225
226 if( NULL != bitmap ) {
227 maug_munlock( *handle_p, bitmap );
228 }
229
230 if( MERROR_OK == retval ) {
231 return RETROGXC_ASSET_TYPE_BITMAP;
232 } else {
233 if( (MAUG_MHANDLE)NULL != *handle_p ) {
234 maug_mfree( *handle_p );
235 }
236 return RETROGXC_ASSET_TYPE_NONE;
237 }
238}
239
240/* === */
241
242#ifdef RETROFONT_PRESENT
243
244retrogxc_asset_type_t retrogxc_loader_font(
245 const maug_path res_p, MAUG_MHANDLE* handle_p, void* data,
246 uint8_t flags
247) {
248 MERROR_RETVAL retval = MERROR_OK;
249 struct RETROGXC_FONT_PARMS* parms = (struct RETROGXC_FONT_PARMS*)data;
250
251 assert( (MAUG_MHANDLE)NULL == *handle_p );
252
253 debug_printf( 1, "loading font into cache: %s (%d, %d, %d)",
254 res_p, parms->glyph_h, parms->first_glyph, parms->glyphs_count );
255
256 retval = retrofont_load( res_p, handle_p,
257 parms->glyph_h, parms->first_glyph, parms->glyphs_count );
258 maug_cleanup_if_not_ok();
259
260cleanup:
261
262 if( MERROR_OK == retval ) {
263 return RETROGXC_ASSET_TYPE_FONT;
264 } else {
265 return RETROGXC_ASSET_TYPE_NONE;
266 }
267}
268
269#endif /* RETROFONT_PRESENT */
270
271/* === */
272
273int16_t retrogxc_load_asset(
274 const maug_path res_p, retrogxc_loader l, void* data,
275 uint8_t flags
276) {
277 int16_t idx = RETROGXC_ERROR_CACHE_MISS,
278 i = 0;
279 struct RETROFLAT_CACHE_ASSET asset_new;
280 struct RETROFLAT_CACHE_ASSET* asset_iter = NULL;
281 retrogxc_asset_type_t asset_type = RETROGXC_ASSET_TYPE_NONE;
282 MERROR_RETVAL retval = MERROR_OK;
283
284 maug_mzero( &asset_new, sizeof( struct RETROFLAT_CACHE_ASSET ) );
285
286 if( 0 == mdata_vector_ct( &gs_retrogxc_bitmaps ) ) {
287 goto just_load_asset;
288 }
289
290 /* Try to find the bitmap already in the cache. */
291 mdata_vector_lock( &gs_retrogxc_bitmaps );
292 for( i = 0 ; mdata_vector_ct( &gs_retrogxc_bitmaps ) > (size_t)i ; i++ ) {
293 asset_iter = mdata_vector_get(
294 &gs_retrogxc_bitmaps, i, struct RETROFLAT_CACHE_ASSET );
295 assert( NULL != asset_iter );
296 debug_printf( RETROGXC_TRACE_LVL, "\"%s\" vs \"%s\"",
297 asset_iter->id, res_p );
298 if( 0 == mfile_cmp_path( asset_iter->id, res_p ) ) {
299 debug_printf( RETROGXC_TRACE_LVL,
300 "found asset \"%s\" at index %d with type %d!",
301 res_p, i, asset_iter->type );
302 idx = i;
303 mdata_vector_unlock( &gs_retrogxc_bitmaps );
304 goto cleanup;
305 }
306 }
307 mdata_vector_unlock( &gs_retrogxc_bitmaps );
308
309just_load_asset:
310
311 /* Bitmap not found. */
312 debug_printf( RETROGXC_TRACE_LVL,
313 "asset %s not found in cache; loading...", res_p );
314
315 /* Call the format-specific loader. */
316 asset_type = l( res_p, &asset_new.handle, data, flags );
317 if( RETROGXC_ASSET_TYPE_NONE != asset_type ) {
318 asset_new.type = asset_type;
319 mfile_assign_path( asset_new.id, res_p, 0 );
320 idx = mdata_vector_append(
321 &gs_retrogxc_bitmaps, &asset_new,
322 sizeof( struct RETROFLAT_CACHE_ASSET ) );
323 if( 0 > idx ) {
324 goto cleanup;
325 }
326 debug_printf( RETROGXC_TRACE_LVL,
327 "asset type %d, \"%s\" assigned cache ID: %d",
328 asset_type, res_p, idx );
329 goto cleanup;
330 }
331
332 /* Still not found! */
333 error_printf( "unable to load asset; cache full or not initialized?" );
334
335cleanup:
336
337 if( MERROR_OK != retval ) {
338 idx = retval * -1;
339 }
340
341 return idx;
342}
343
344/* === */
345
346MAUG_MHANDLE retrogxc_get_asset(
347 size_t asset_idx, retrogxc_asset_type_t asset_type
348) {
349 MAUG_MHANDLE handle_out = (MAUG_MHANDLE)NULL;
350 MERROR_RETVAL retval = MERROR_OK;
351 struct RETROFLAT_CACHE_ASSET* asset = NULL;
352
353 assert( (MAUG_MHANDLE)NULL != gs_retrogxc_bitmaps.data_h );
354
355 mdata_vector_lock( &gs_retrogxc_bitmaps );
356
357 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= asset_idx ) {
358 error_printf( "invalid asset index: " SIZE_T_FMT, asset_idx );
359 goto cleanup;
360 }
361
362 asset = mdata_vector_get(
363 &gs_retrogxc_bitmaps, asset_idx, struct RETROFLAT_CACHE_ASSET );
364
365 if( asset_type != asset->type ) {
366 error_printf(
367 "index " SIZE_T_FMT
368 " not present in cache or not requested type %d (%d)!",
369 asset_idx, asset_type, asset->type );
370 goto cleanup;
371 }
372
373 handle_out = asset->handle;
374
375cleanup:
376
377 if( MERROR_OK != retval ) {
378 handle_out = NULL;
379 }
380
381 mdata_vector_unlock( &gs_retrogxc_bitmaps );
382
383 return handle_out;
384}
385
386/* === */
387
388MERROR_RETVAL retrogxc_blit_bitmap(
389 retroflat_blit_t* target, size_t bitmap_idx,
392 retroflat_pxxy_t w, retroflat_pxxy_t h, int16_t instance
393) {
394 MERROR_RETVAL retval = MERROR_OK;
395 struct RETROFLAT_CACHE_ASSET* asset = NULL;
396 retroflat_blit_t* bitmap = NULL;
397
398 assert( (MAUG_MHANDLE)NULL != gs_retrogxc_bitmaps.data_h );
399
400 mdata_vector_lock( &gs_retrogxc_bitmaps );
401
402 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= bitmap_idx ) {
403 error_printf( "invalid bitmap index: " SIZE_T_FMT, bitmap_idx );
404 retval = MERROR_OVERFLOW;
405 goto cleanup;
406 }
407
408 asset = mdata_vector_get(
409 &gs_retrogxc_bitmaps, bitmap_idx, struct RETROFLAT_CACHE_ASSET );
410
411 if( RETROGXC_ASSET_TYPE_BITMAP != asset->type ) {
412 error_printf(
413 "index " SIZE_T_FMT " not present in cache or not bitmap (%d)!",
414 bitmap_idx, asset->type );
415 retval = MERROR_FILE;
416 goto cleanup;
417 }
418
419 maug_mlock( asset->handle, bitmap );
420
421 retval = retroflat_2d_blit_bitmap(
422 target, bitmap, s_x, s_y, d_x, d_y, w, h, instance );
423
424cleanup:
425
426 if( NULL != bitmap ) {
427 maug_munlock( asset->handle, bitmap );
428 }
429
430 mdata_vector_unlock( &gs_retrogxc_bitmaps );
431
432 return retval;
433}
434
435/* === */
436
437MERROR_RETVAL retrogxc_bitmap_wh(
438 size_t bitmap_idx, retroflat_pxxy_t* p_w, retroflat_pxxy_t* p_h
439) {
440 MERROR_RETVAL retval = MERROR_OK;
441 struct RETROFLAT_CACHE_ASSET* asset = NULL;
442 retroflat_blit_t* bitmap = NULL;
443
444 mdata_vector_lock( &gs_retrogxc_bitmaps );
445
446 if( mdata_vector_ct( &gs_retrogxc_bitmaps ) <= bitmap_idx ) {
447 error_printf( "invalid bitmap index: " SIZE_T_FMT, bitmap_idx );
448 retval = MERROR_OVERFLOW;
449 goto cleanup;
450 }
451
452 asset = mdata_vector_get(
453 &gs_retrogxc_bitmaps, bitmap_idx, struct RETROFLAT_CACHE_ASSET );
454
455 if( RETROGXC_ASSET_TYPE_BITMAP != asset->type ) {
456 error_printf(
457 "index " SIZE_T_FMT " not present in cache or not bitmap (%d)!",
458 bitmap_idx, asset->type );
459 retval = MERROR_FILE;
460 goto cleanup;
461 }
462
463 maug_mlock( asset->handle, bitmap );
464
465 if( NULL != p_w ) {
466 *p_w = retroflat_2d_bitmap_w( bitmap );
467 }
468
469 if( NULL != p_h ) {
470 *p_h = retroflat_2d_bitmap_h( bitmap );
471 }
472
473cleanup:
474
475 if( NULL != bitmap ) {
476 maug_munlock( asset->handle, bitmap );
477 }
478
479 mdata_vector_unlock( &gs_retrogxc_bitmaps );
480
481 return retval;
482}
483
484/* === */
485
486#ifdef RETROFONT_PRESENT
487
488int16_t retrogxc_load_font(
489 const maug_path font_name,
490 uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count
491) {
492 int16_t idx = -1;
493 struct RETROGXC_FONT_PARMS parms;
494
495 parms.glyph_h = glyph_h;
496 parms.first_glyph = first_glyph;
497 parms.glyphs_count = glyphs_count;
498
499 idx = retrogxc_load_asset( font_name, retrogxc_loader_font, &parms, 0 );
500
501 return idx;
502}
503
504#endif /* RETROFONT_PRESENT */
505
506#endif /* RETROGXC_C */
507 /* maug_retroflt */
509 /* maug_retrogxc */
511
512#endif /* !RETROGXC_H */
513
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:28
#define mfile_cmp_path(a, b)
Compare two asset paths. Return 0 if they're the same.
Definition mfile.h:146
MERROR_RETVAL mfile_assign_path(maug_path tgt, const maug_path src, uint8_t flags)
Copy a maug_path from one place to another, safely observing character limits, etc.
char maug_path[MAUG_PATH_SZ_MAX]
Path/name used to load an asset from disk or access other files.
Definition mfile.h:141
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition retroflt.h:885
int16_t retrogxc_load_asset(const maug_path res_p, retrogxc_loader l, void *data, uint8_t flags)
Try to load an asset by file path. Return a cached copy if it's already been loaded.
MAUG_MHANDLE retrogxc_get_asset(size_t asset_idx, retrogxc_asset_type_t asset_type)
Retrive an asset for which we have a prior cached index.
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:108
Definition retrogxc.h:57
Definition retrogxc.h:63