1 #ifndef _BMPMAN_H
2 #define _BMPMAN_H
3 /*
4  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
5  *
6  * All source code herein is the property of Volition, Inc. You may not sell
7  * or otherwise commercially exploit the source or things you created based on the
8  * source.
9  *
10  */
11 
12 /**
13  * @file bmpman.h
14  * Header file for the bitmap manager (bmpman)
15  */
16 
17 /**
18  * @example bm_examples.cpp
19  * @brief This containes examples of bmpman usage
20  */
21 
22 #include "cfile/cfile.h"
23 #include "globalincs/pstypes.h"
24 
25 #ifndef NDEBUG
26 #define BMPMAN_NDEBUG	//!< Enables BMPMAN debugging code
27 #endif
28 
29 /**
30  * @defgroup BMPMAN_CONSTANTS Macro constants used in/with bmpman.h
31  *
32  * @{
33  */
34 
35 // Flag positions for bitmap.flags
36 // ***** NOTE:  bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
37 #define	BMP_AABITMAP        (1<<0)      //!< antialiased bitmap
38 #define	BMP_TEX_XPARENT     (1<<1)      //!< transparent texture
39 #define	BMP_TEX_OTHER       (1<<2)      //!< so we can identify all "normal" textures
40 #define BMP_TEX_DXT1        (1<<3)      //!< dxt1 compressed 8r8g8b1a (24bit)
41 #define BMP_TEX_DXT3        (1<<4)      //!< dxt3 compressed 8r8g8b4a (32bit)
42 #define BMP_TEX_DXT5        (1<<5)      //!< dxt5 compressed 8r8g8b8a (32bit)
43 #define BMP_TEX_BC7			(1<<6)		//!< BC7  compressed 8r8g8b8a (32bit)
44 #define BMP_TEX_CUBEMAP     (1<<7)      //!< a texture made for cubic environment map
45 #define BMP_MASK_BITMAP     (1<<8)      //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
46 
47 // Combined flags
48 #define BMP_TEX_COMP        ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 | BMP_TEX_BC7 )  //!< Compressed textures
49 #define BMP_TEX_NONCOMP     ( BMP_TEX_XPARENT | BMP_TEX_OTHER )             //!< Non-compressed textures
50 #define	BMP_TEX_ANY         ( BMP_TEX_COMP | BMP_TEX_NONCOMP )              //!< Any texture
51 
52 // Flag positions for bitmap.type
53 #define BMP_FLAG_RENDER_TARGET_STATIC       (1<<0)      //!< Texture is a static type
54 #define BMP_FLAG_RENDER_TARGET_DYNAMIC      (1<<1)      //!< Texture is a dynamic type (animation)
55 #define BMP_FLAG_CUBEMAP                    (1<<2)      //!< Texture is a cubemap
56 
57 // Bitmap types
58 enum BM_TYPE
59 {
60 	BM_TYPE_NONE = 0,   //!< No type
61 	BM_TYPE_USER,       //!< in-memory
62 	BM_TYPE_PCX,        //!< PCX
63 	BM_TYPE_TGA,        //!< 16 or 32 bit targa
64 	BM_TYPE_DDS,        //!< generic identifier for DDS
65 	BM_TYPE_PNG,        //!< PNG
66 	BM_TYPE_JPG,        //!< 32 bit jpeg
67 	BM_TYPE_ANI,        //!< in-house ANI format
68 	BM_TYPE_EFF,        //!< specifies any type of animated image, the EFF itself is just text
69 
70 	// special types
71 	BM_TYPE_RENDER_TARGET_STATIC,   //!< 24/32 bit setup internally as a static render target
72 	BM_TYPE_RENDER_TARGET_DYNAMIC,  //!< 24/32 bit setup internally as a dynamic render target
73 
74 	// Compressed types (bitmap.c_type)
75 	BM_TYPE_DXT1,           //!< 24 bit with switchable alpha
76 	BM_TYPE_DXT3,           //!< 32 bit with 4 bit alpha
77 	BM_TYPE_DXT5,           //!< 32 bit with 8 bit alpha
78 	BM_TYPE_BC7,			//!< 32-bit with variable alpha
79 	BM_TYPE_CUBEMAP_DDS,    //!< generic DDS cubemap (uncompressed cubemap surface)
80 	BM_TYPE_CUBEMAP_DXT1,   //!< 24-bit cubemap        (compressed cubemap surface)
81 	BM_TYPE_CUBEMAP_DXT3,   //!< 32-bit cubemap        (compressed cubemap surface)
82 	BM_TYPE_CUBEMAP_DXT5    //!< 32-bit cubemap        (compressed cubemap surface)
83 };
84 
85 /**
86  * @}
87  */
88 
89 struct bitmap
90 {
91 	short	w;          //!< Width, in number of pixels
92 	short	h;          //!< Height, in number of pixels
93 	short	rowsize;    //!< What you need to add to go to next row
94 	int	bpp;        //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
95 	int	true_bpp;   //!< The image's actual bitdepth
96 	ushort	flags;      //!< Various texture type flags. @see BMPMAN_CONSTANTS
97 	ptr_u	data;       //!< Pointer to data, or maybe offset into VRAM.
98 	ubyte *palette;     /**< @brief   Pointer to this bitmap's palette (if it has one).
99 	                     *   @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
100 	                     */
101 };
102 
103 // Forward definition for the graphics API
104 struct bitmap_entry;
105 struct bitmap_slot;
106 
107 extern size_t bm_texture_ram;  //!< how many bytes of textures are used.
108 
109 extern int Bm_paging;   //!< Bool type that indicates if BMPMAN is currently paging.
110 
111 extern const BM_TYPE bm_type_list[];       //!< List of valid bitmap types
112 extern const char *bm_ext_list[];        //!< List of extensions for those types
113 extern const int BM_NUM_TYPES;           //!< Calculated number of bitmap types
114 extern const BM_TYPE bm_ani_type_list[];   //!< List of valid bitmap animation types
115 extern const char *bm_ani_ext_list[];    //!< List of extensions for those types
116 extern const int BM_ANI_NUM_TYPES;       //!< Calculated number of bitmap animation types
117 
118 extern int ENVMAP;      //!< References a map that is for environment mapping -Bobboau
119 
120 /**
121  * @brief Initilizes the bitmap manager
122  */
123 void bm_init();
124 
125 /**
126  * @brief Closes the bitmap manager, freeing any allocated memory used by bitmaps. Is called at program close.
127  */
128 void bm_close();
129 
130 #define BMP_FLAG_RENDER_TARGET_STATIC		(1<<0)
131 #define BMP_FLAG_RENDER_TARGET_DYNAMIC		(1<<1)
132 #define BMP_FLAG_CUBEMAP					(1<<2)
133 #define BMP_FLAG_RENDER_TARGET_MIPMAP		(1<<3)
134 
135 /**
136  * @brief Allocates memory for the given handle.
137  *
138  * @returns A pointer to the allocated vm if successful,
139  * @returns Null, if unsuccessful
140  *
141  * @note z64 - This function looks fishy. Not only is handle not used in release builds, but bm_bitmaps[handle].size
142  *   and bm_texture_size aren't modified unless this is a debug build
143  */
144 void *bm_malloc(int handle, size_t size);
145 
146 /**
147  * @brief (DEBUG) Similar to bm_malloc, but only updates how much memory is used
148  *
149  * @note z64 - Also fishy (see bm_malloc)
150  */
151 void bm_update_memory_used(int n, size_t size);
152 
153 class bitmap_lookup {
154 	ubyte *Bitmap_data;
155 
156 	int Width;
157 	int Height;
158 	int Num_channels;
159 
160 	float map_texture_address(float address);
161 public:
162 	bitmap_lookup(int bitmap_num);
163 	~bitmap_lookup();
164 
165 	bool valid();
166 
167 	float get_channel_alpha(float u, float v);
168 };
169 
170 void clear_bm_lookup_cache();
171 
172 /**
173  * @brief Loads a bitmap so we can draw with it later.
174  *
175  * @param filename
176  *
177  * @returns The bitmap number if successful, else
178  * @returns a negative value if not
179  */
180 int bm_load(const char* filename);
181 
182 /**
183  * @brief Loads a bitmap so we can draw with it later. (Preferred version)
184  *
185  * @param filename
186  *
187  * @returns The bitmap number if successful, else
188  * @returns a negative value if not
189  */
190 int bm_load(const SCP_string& filename);
191 
192 /**
193  * @brief Reloads a bitmap as a duplicate.
194  *
195  * @details This function basically allows you to load a bitmap which already exists (by filename). This is useful
196  *   because in some cases we need to have a bitmap which is locked in screen format _and_ texture format, such as
197  *   the pilot pics and squad logos
198  *
199  * @param filename
200  *
201  * @returns The bitmap number if successful, else
202  * @returns a negative value if not
203  */
204 int bm_load_duplicate(const char *filename);
205 
206 /**
207  * Loads a bitmap which exists somewhere in the RAM.
208  *
209  * @param bpp The bitdepth of the bitmap
210  * @param w The width of the bitmap
211  * @param h The height of the bitmap
212  * @param[in] data The bitmap's data glob
213  * @param flags
214  *
215  * @note The used RAM cannot be freed until bm_release is called on the created bitmap
216  */
217 int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
218 
219 /**
220  * @brief Unloads a bitmap's data, but not the bitmap info
221  *
222  * @details The bm number (n) may be reused once this function has been called on it. However, it will have to be paged
223  *   in the next time it is locked.
224 
225  * @param handle                The index number of the bitmap to free
226  * @param clear_render_targets  If true, release a render target
227  * @param nodebug               If true, exclude certain debug messages
228  *
229  * @returns 0 if not successful,
230  * @returns 1 if successful
231  */
232 int bm_unload(int handle, int clear_render_targets = 0, bool nodebug = false);
233 
234 /**
235  * @brief Quickly unloads a bitmap's data, ignoring the load_count
236  *
237  * @details Similar to bm_unload(), except that it can be safely used to free data without worrying about load_count.
238  *   It's safe to use in relation to bm_release() and in gr_*_texture functions
239  *
240  * @param handle                The bm number of the bitmap to free
241  * @param clear_render_targets  If true, release a render target
242  *
243  * @note bm_free_data_fast() is used here and NOT bm_free_data()
244  */
245 int bm_unload_fast(int handle, int clear_render_targets = 0);
246 
247 /**
248  * @brief Frees both a bitmap's data and it's associated slot.
249  *
250  * @details Once called, the bm number 'n' cannot be used until bm_load or bm_create is re-inits the slot.
251  *
252  * @param handle               The index number of the bitmap to release
253  * @param clear_render_targets If nonzero, also release render targets
254  *
255  * @returns 1 on success,
256  * @returns 0 otherwise
257  *
258  * @note If the passed handle is that of an ANI, it frees EVERY frame. Be sure to only pass the handle of the first frame!
259  *
260  * @todo upgrade return type and clear_render_targets type to bools
261  */
262 int bm_release(int handle, int clear_render_targets = 0);
263 
264 /**
265  * @brief Detaches the render target of a bitmap if it exists
266  *
267  * @details Once called, this handle cannot be used as a target to switch the rendering context to
268  *
269  * @param handle               The index number of the bitmap to release
270  *
271  * @returns 1 on success,
272  * @returns 0 otherwise
273  *
274  * @note If the passed handle is that of an ANI, it frees the render target of EVERY frame. Be sure to only pass the handle of the first frame!
275  *
276  */
277 bool bm_release_rendertarget(int handle);
278 
279 /**
280  * @brief Loads a bitmap sequance so we can draw with it.
281  *
282  * @param[in] filename
283  * @param[out] nframes          If non-null, set to the number of frames the animation has
284  * @param[out] fps              If non-null, set to the fps of this animation
285  * @param[out] keyframe         if non null, set to the keyframe index of this animation
286  * @param[in] can_drop_frames   If set, allows dropped frames
287  * @param[in] dir_type          Directory type
288  *
289  * @returns The bm number of the first bitmap in the sequence if successful, or
290  * @returns A negative value if unsuccessful
291  */
292 int bm_load_animation(const char *filename, int *nframes = nullptr, int *fps = nullptr, int *keyframe = nullptr, float *total_time = nullptr, bool can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
293 
294 /**
295  * @brief Loads either animation (bm_load_animation) or still image (bm_load)
296  *
297  * @param[in] filename
298  * @param[out] nframes  If non-null and loading was successful, set to the number of frames the animation has
299  * @param[out] fps      If non-null and loading was successful, set to the fps of this animation
300  * @param[out] keyframe if non null and loading was successful, set to the keyframe index of this animation
301  * @param[in] can_drop_frames
302  * @param[in] dir_type
303  *
304  * @returns The bm number of the first bitmap in the sequence if successful, or
305  * @returns A negative value if unsuccessful
306  */
307 int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, bool can_drop_frames = false, int dir_type = CF_TYPE_ANY);
308 
309 /**
310  * @brief Locks down the bitmap indexed by bitmapnum.
311  *
312  * @details Also converts the bitmap to the appropriate format specified by bpp and flags. Only lock a bitmap when you
313  *   need it!
314  *
315  * @param handle    The number indexing the desired bitmap
316  * @param bpp       The desired bpp of the bitmep
317  * @param flags     The desired bitmap format
318  * @param nodebug
319 
320  * @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
321  * @returns NULL if unsuccessful
322  */
323 bitmap* bm_lock(int handle, int bpp, ushort flags, bool nodebug = false);
324 
325 /**
326  * @brief Returns the image type of the given bitmap handle
327  */
328 BM_TYPE bm_get_type(int handle);
329 
330 /**
331  * @brief Unlocks a bitmap
332  *
333  * @details Decrements the ref_count member of the bitmap_entry struct, A bitmap can only be unloaded when the
334  * ref_count is 0
335  */
336 void bm_unlock(int handle);
337 
338 /**
339  * @brief Checks if the bitmap indexed by handle is valid
340  *
341  * @details Some early known false or out of range handles (such as negative) are checked within
342  * an initial routine pass, followed by a more thorough check routine to ensure the
343  * series of bitmaps within the bm_bitmaps[] structure have not become invalid.
344  *
345  * @returns Nonzero if valid, else
346  * @returns Zero otherwise
347  *
348  * @todo z64 - Returned value is essentially a bool type, need to check all caller functions to see if it can safely
349  *   be updated to reflect this
350  */
351 int bm_is_valid(int handle);
352 
353 /**
354  * @brief Gets info on the bitmap indexed by handle.
355  *
356  * @param[out] w      If non-null, gets the width
357  * @param[out] h      If non-null, gets the heigth
358  * @param[out] flags  If non-null, gets the flags
359  * @param[out] nframs If non-null, gets the nframes
360  * @param[out] fps    If non-null, gets the fps
361  *
362  * @returns The handle on success, or
363  * @returns The handle to the first frame on success, or
364  * @returns -1 on failure
365  */
366 int bm_get_info(int handle, int *w = nullptr, int * h = nullptr, ushort* flags = nullptr, int *nframes = nullptr, int *fps = nullptr);
367 
368 /**
369  * @brief Gets the filename of the bitmap indexed by handle
370  *
371  * @param[out] filename The filename of the bitmap, if successful. Is set to an empty string if unseccessful
372  *
373  * @todo z64 - maybe deprecate this in favor of an SCP_string version
374  */
375 void bm_get_filename(int bitmapnum, char *filename);
376 
377 /**
378  * @brief Gets the filename of the bitmap indexed by handle, which must exist.
379  *
380  * @details If the bitmap does not exist (i.e. the handle is invalid), then an Assertion halts program execution.
381  *
382  * @returns A const char* to the filename of the bitmap
383  *
384  * @todo z64 - maybe deprecate this in favor of an SCP_string version.
385  * @todo z64 - maybe combine this with the other bm_get_filename function like so:
386  *   void bm_get_filename(int handle, SCP_string *filename, bool must_exist = false);
387  */
388 const char *bm_get_filename(int handle);
389 
390 /**
391  * @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
392  *
393  * @todo Maybe move this declaration into bmpman.cpp and then extern this function within game_shutdown() to
394  *  ensure it only ever gets called there.
395  */
396 void bm_unload_all();
397 
398 /**
399  * @brief Gets the palette for a given bitmap indexed by handle, and optionally the filename
400  *
401  * @param[out] pal Is set to reference the bitmap's palette
402  * @param[out] name (optional) Is set to the bitmap's filename
403  *
404  * @todo Maybe get rid of the optional filename and have the callers call bm_get_filename. Less efficient, however.
405  */
406 void bm_get_palette(int handle, ubyte *pal, char *name);
407 
408 /**
409  * @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
410  *
411  * @details Both params are non-optional, and must be non-null. There's currently no safety checks on either.
412  *
413  * @param ntotal[out] Memory size, in bytes, of the locked bitmaps
414  * @param nnew[out]   Memory size, in bytes, of the bitmaps that were locked since the last frame
415  *
416  * @note This is a debug function, and is undefined within release builds
417  */
418 void bm_get_frame_usage(int *ntotal, int *nnew);
419 
420 /**
421  * @brief Reloads an existing bmpman slot with different bitmap
422  *
423  * @param[in] filename The filename of the image to load
424  *
425  * @returns The bitmap handle on success, or
426  * @returns A negative value on failure
427  *
428  * @note This should only be used if you are certain the new picture is the same type, has same dimensions, etc.
429  */
430 int bm_reload(int bitmap_handle, const char* filename);
431 
432 /**
433  * @brief Tells bmpman to start keeping track of what bitmaps are used where
434  */
435 void bm_page_in_start();
436 
437 /**
438  * @brief Tells bmpman to stop paging (?)
439  */
440 void bm_page_in_stop();
441 
442 // Paging code in a library should call these functions
443 // in its page in function.
444 
445 /**
446  * @brief Marks a texture as being used for this level
447  *
448  * @param[in] num_frames If specified, assumes this is an animated texture
449  */
450 void bm_page_in_texture(int bitmapnum, int num_frames = 0);
451 
452 /**
453  * @brief Marks a textures as being used for level and is transparant
454  *
455  * @param[in] num_frames If specified, assumes this is an animated texture
456  */
457 void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
458 
459 /**
460  * @brief Marks a texture as being used for this level, and is anti-aliased
461  *
462  * @param[in] num_frames If specified, assumes this is an animated texture
463  */
464 void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
465 
466 /**
467  * @brief Sets BMPMAN's memory mode
468  *
469  * @details 0 = High memory;
470  *          1 = Low memory (loads every other frame of ani's);
471  *          2 = Debug low memory (only use first frame of each ani)
472  *
473  * @todo This should use an enum, or instead allow an arbitrary number to drop frames (like 1/2, 1/3, etc.)
474  */
475 void bm_set_low_mem(int mode);
476 
477 /**
478  * @brief Sets bm_set_components and bm_get_components to reference screen format functions
479  */
480 void BM_SELECT_SCREEN_FORMAT();
481 
482 /**
483  * @brief Sets bm_set_components and bm_get_components to reference texture format functions
484  */
485 void BM_SELECT_TEX_FORMAT();
486 
487 /**
488  * @brief Sets bm_set_components and bm_get_components to reference texture format functions (with alpha)
489  */
490 void BM_SELECT_ALPHA_TEX_FORMAT();
491 
492 /**
493  * @brief Functional pointer that references any of the bm_set_components functions.
494  *
495  * @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
496  * format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
497  *
498  * @param[out] pixel The pixel to set
499  * @param[in] r Red value   (may not be NULL)
500  * @param[in] g Green value (may not be NULL)
501  * @param[in] b Blue value  (may not be NULL)
502  * @param[in] a Alpha value (currently ignored)
503  *
504  * @note z64 - These functions were made predating the introduction of C++ classes, and are basically the equivalent
505  * of Pixel::set(ubyte *r, ubyte *b, ubyte *g). The original comment mentions that any of the rgba params may be
506  * NULL, but this is by far _NOT_ the case, as a NULL value will cause undefined behavior (really really bad chroma
507  * corruption)
508  *
509  * @note These functions assume the incoming bitdepth will always be >= to the outgoing bitdepth of the pixel. Should
510  * the incoming bitdepth be lower, the outgoing values will appear darker than they should be
511  */
512 extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
513 
514 /**
515  * @brief Sets the 16bpp screen pixel to the specified RGBA value
516  *
517  * @see bm_set_components
518  */
519 void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
520 
521 /**
522  * @brief Sets the 16bpp texture pixel to the specified RGBA value
523  *
524  * @see bm_set_components
525  */
526 void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
527 
528 /**
529  * @brief Sets the 32bpp texture pixel to the specified RGBA value
530  *
531  * @see bm_set_components
532  */
533 void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
534 
535 /**
536  * @brief Gets the RGBA components of a pixel according to the selected mode
537  *
538  * @see BM_SELECT_SCREEN_FORMAT() BM_SELECT_TEX_FORMAT() BM_SELECT_ALPHA_TEX_FORMAT()
539  */
540 void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
541 
542 extern int ENVMAP;	//this holds a reference to a map that is for environment mapping -Bobboau
543 
544 /**
545  * @brief Returns the compression type of the bitmap indexed by handle
546  */
547 int bm_is_compressed(int handle);
548 
549 /**
550  * @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
551  */
552 int bm_get_tcache_type(int handle);
553 
554 
555 /**
556  * @brief Gets the number of mipmaps of the indexed texture
557  */
558 int bm_get_num_mipmaps(int handle);
559 
560 /**
561  * @brief Checks to see if the indexed bitmap has an alpha channel
562  *
563  * @note Currently just checks if the bitmap is 32bpp and is not a .PCX
564  */
565 bool bm_has_alpha_channel(int handle);
566 
567 /**
568  * @brief (DEBUG) Prints all loaded bitmaps to an outwindow
569  */
570 void bm_print_bitmaps();
571 
572 /**
573  * @brief Creates a render target as close to the desired resolution as possible.
574  *
575  * @returns the handle of an avilable render target if successful, or
576  * @returns -1 if not successful
577  *
578  * @note BM_FLAG_RENDER_TARGET_STATIC are drawn once/infrequently, while BM_FLAG_RENDER_TARGET_DYNAMIC are drawn roughly once every frame
579  */
580 int bm_make_render_target(int width, int height, int flags);
581 
582 /**
583  * @brief Checks to see if the given bitmap indexed by handle is a render target
584  *
585  * @returns The render type (BM_TYPE) if it is a render target, or
586  * @returns 0 if it is not
587  */
588 int bm_is_render_target(int handle);
589 
590 /**
591  * @brief (GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle
592  *
593  * @returns true if successful, or
594  * @returns false if unsuccessful
595  */
596 bool bm_set_render_target(int handle, int face = -1);
597 
598 /**
599  * @brief Loads and parses an .EFF
600  *
601  * @param[in]  filename The filename of the .EFF
602  * @param[in]  dir_type
603  * @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
604  * @param[out] nfps    (optional) If given, is set to the fps of this .EFF
605  * @param[out] key     (optional) If given, is set to the keyframe index of this .EFF
606  * @param[out] type    (optional) If given, is set to the BM_TYPE of the .EFF
607  *
608  * @returns true If successful
609  * @returns false If not successful
610  */
611 bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type);
612 
613 /**
614  * @brief Calculates & returns the current frame of an animation
615  *
616  * @param[in] frame1_handle  Handle of the animation
617  * @param[in] elapsed_time   Time in seconds since the animation started playing
618  * @param[in] loop           (optional) specifies if the animation should loop, default is false which causes animation to hold on the last frame
619  * @param[in] divisor        (optional) if greater than zero, elapsed time will be divided by this value i.e. allows "percentage complete" to be used to determine the frame instead of the animations total time derived from fps * frames
620  *
621  * @returns current frame of the animation (range is zero to the number of frames minus one)
622  */
623 int bm_get_anim_frame(const int frame1_handle, float elapsed_time, const float divisor = 0.0f, const bool loop = false);
624 
625 /**
626  * @brief Determines if the given handle could be used in a texture array
627  *
628  * @param handle The handle to query the value for
629  * @return @c true if all frames have the same size, @c false otherwise. Always returns @c true for single images
630  */
631 bool bm_is_texture_array(const int handle);
632 
633 /**
634  * @brief Gets the base frame of the specified animation
635  *
636  * @details The base frame is the frame of the animation that should be used to determine if two animation frames can be
637  * used in the same draw call. Use this if you want to optimize your draw calls to make use of texture arrays.
638  *
639  * @param handle The handle of the animation to check. This may also be a single frame bitmap
640  * @param num_frames Optionally return the number of frames in the animation
641  * @return The bitmap handle of the base frame or -1 on error
642  */
643 int bm_get_base_frame(const int handle, int* num_frames = nullptr);
644 
645 /**
646  * @brief Get the array index of the specified bitmap
647  *
648  * This should be used when passing the array index to the GPU (e.g. when building uniform structs or streaming particle
649  * data)
650  *
651  * @param handle The handle of the bitmap
652  * @return The index into the array
653  */
654 int bm_get_array_index(const int handle);
655 
656 /**
657  * @brief Counts how many slots are used in bm_bitmaps
658  *
659  * This needs to iterate through all the slots in order to determine whether or not they're used, so shouldn't be used frivolously.
660  *
661  * @return The number of used slots
662  */
663 int bmpman_count_bitmaps();
664 
665 /**
666  * @brief Counts how many slots are available to the bmpman system
667  *
668  * Since the number of slots is dynamic now, this should be used for determining the total amount of available slots at
669  * the moment.
670  *
671  * @warning This is entirely for debugging and logging purposes. It should not be used in actual engine code.
672  *
673  * @return The number of available slots
674  */
675 int bmpman_count_available_slots();
676 
677 /**
678  * @brief Checks if the given filename is a valid effect or texture file name
679  *
680  * @note At least one of @c single_frame or @c animation must be true since the result would make no sense otherwise. It
681  * is also valid to set both parmeters to @c true.
682  *
683  * @todo This currently just tries to load the file but could be improved by not actually loading the file in the future.
684  *
685  * @param file The file name to check
686  * @param single_frame If set to @c true then single frames are valid files
687  * @param animation If set to @c true then animations are valid files
688  * @return @c true if the file name is valid, @c false otherwise
689  */
690 bool bm_validate_filename(const SCP_string& file, bool single_frame, bool animation);
691 
692 SDL_Surface* bm_to_sdl_surface(int handle);
693 
694 #endif
695