Advertisement
MageKing17

Untitled

Dec 13th, 2015
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 164.37 KB | None | 0 0
  1. From a75c0d4b3983d3f3fcf7ab8729f05418cfddd11b Mon Sep 17 00:00:00 2001
  2. From: Bryan Dunsheng See <bryan.see@live.com>
  3. Date: Mon, 14 Dec 2015 00:28:53 +0800
  4. Subject: [PATCH] Cleared unused functions from bmpman code; added ID code
  5.  
  6. ---
  7. code/bmpman/bm_internal.h |    1 +
  8.  code/bmpman/bmpman.cpp    | 3655 ++++++++++++++++++++++++---------------------
  9.  code/bmpman/bmpman.h      |  833 +++--------
  10.  3 files changed, 2142 insertions(+), 2347 deletions(-)
  11.  
  12. diff --git a/code/bmpman/bm_internal.h b/code/bmpman/bm_internal.h
  13. index cf324fe..1b2b21b 100644
  14. --- a/code/bmpman/bm_internal.h
  15. +++ b/code/bmpman/bm_internal.h
  16. @@ -48,6 +48,7 @@ union bm_extra_info {
  17.  
  18.  struct bitmap_entry {
  19.     // identification
  20. +   int id;                         //!< ID for this bitmap
  21.     char filename[MAX_FILENAME_LEN];    //!< filename for this bitmap
  22.  
  23.     uint signature;         //!< a unique signature identifying the data
  24. diff --git a/code/bmpman/bmpman.cpp b/code/bmpman/bmpman.cpp
  25. index e25bb0b..65714b4 100644
  26. --- a/code/bmpman/bmpman.cpp
  27. +++ b/code/bmpman/bmpman.cpp
  28. @@ -1,380 +1,361 @@
  29.  /*
  30. - * Copyright (C) Volition, Inc. 1999.  All rights reserved.
  31. - *
  32. - * All source code herein is the property of Volition, Inc. You may not sell
  33. - * or otherwise commercially exploit the source or things you created based on the
  34. - * source.
  35. - *
  36. +* Copyright (C) Volition, Inc. 1999.  All rights reserved.
  37. +*
  38. +* All source code herein is the property of Volition, Inc. You may not sell
  39. +* or otherwise commercially exploit the source or things you created based on the
  40. +* source.
  41. +*
  42.  */
  43. -#ifndef NDEBUG
  44. -#define BMPMAN_NDEBUG
  45. -#endif
  46.  
  47. -#define BMPMAN_INTERNAL
  48. +
  49. +
  50. +#include <ctype.h>
  51. +
  52. +#include "globalincs/pstypes.h"
  53.  
  54.  #ifdef _WIN32
  55. -#include <windows.h>
  56. +#include <windows.h>   // for MAX_PATH
  57.  #endif
  58.  
  59. -#include "anim/animplay.h"
  60. -#include "anim/packunpack.h"
  61. -#include "bmpman/bm_internal.h"
  62. +#include <limits.h>        // for MAX_INT
  63. +
  64.  #include "bmpman/bmpman.h"
  65. -#include "ddsutils/ddsutils.h"
  66. -#include "debugconsole/console.h"
  67. -#include "globalincs/systemvars.h"
  68. +#include "pcxutils/pcxutils.h"
  69. +#include "palman/palman.h"
  70.  #include "graphics/2d.h"
  71. -#include "graphics/grinternal.h"
  72. -#include "io/key.h"
  73. +#include "anim/animplay.h"
  74.  #include "io/timer.h"
  75. +#include "globalincs/systemvars.h"
  76. +#include "io/key.h"
  77. +#include "anim/packunpack.h"
  78. +#include "graphics/grinternal.h"
  79. +#include "tgautils/tgautils.h"
  80. +#include "ship/ship.h"
  81. +#include "ddsutils/ddsutils.h"
  82. +#include "cfile/cfile.h"
  83. +#include "pngutils/pngutils.h"
  84.  #include "jpgutils/jpgutils.h"
  85. -#include "network/multiutil.h"
  86. -#include "palman/palman.h"
  87.  #include "parse/parselo.h"
  88. -#include "pcxutils/pcxutils.h"
  89. -#include "pngutils/pngutils.h"
  90. -#include "ship/ship.h"
  91. -#include "tgautils/tgautils.h"
  92. +#include "network/multiutil.h"
  93. +#include "debugconsole/console.h"
  94.  
  95. -#include <ctype.h>
  96. -#include <limits.h>
  97. +#define BMPMAN_INTERNAL
  98. +#include "bmpman/bm_internal.h"
  99. +
  100. +extern int Cmdline_cache_bitmaps;
  101.  
  102. -// --------------------------------------------------------------------------------------------------------------------
  103. -// Private macros.
  104. +#ifndef NDEBUG
  105. +#define BMPMAN_NDEBUG
  106. +#endif
  107.  
  108. -/**
  109. - * @todo upgrade this to an inline funciton, taking bitmap_entry and const char* as arguments
  110. - */
  111. -#define EFF_FILENAME_CHECK { if ( be->type == BM_TYPE_EFF ) strcpy_s( filename, be->info.ani.eff.filename ); else strcpy_s( filename, be->filename ); }
  112. -// --------------------------------------------------------------------------------------------------------------------
  113. -// Monitor variables
  114. -MONITOR(NumBitmapPage)
  115. -MONITOR(SizeBitmapPage)
  116.  
  117. -// --------------------------------------------------------------------------------------------------------------------
  118. -// Definition of public variables (declared as extern in bmpman.h).
  119. +// globals
  120.  int GLOWMAP = -1;
  121.  int SPECMAP = -1;
  122. -int ENVMAP  = -1;
  123. +int ENVMAP = -1;
  124.  int NORMMAP = -1;
  125.  int HEIGHTMAP = -1;
  126.  int MISCMAP = -1;
  127.  
  128. +bitmap_entry bm_bitmaps[MAX_BITMAPS];
  129. +
  130.  int bm_texture_ram = 0;
  131. +int bm_inited = 0;
  132.  int Bm_paging = 0;
  133.  
  134. -// Extension type lists
  135. -const BM_TYPE bm_type_list[] = { BM_TYPE_DDS, BM_TYPE_TGA, BM_TYPE_PNG, BM_TYPE_JPG, BM_TYPE_PCX };
  136. -const char *bm_ext_list[] = { ".dds", ".tga", ".png", ".jpg", ".pcx" };
  137. -const int BM_NUM_TYPES = sizeof(bm_type_list) / sizeof(bm_type_list[0]);
  138. +// locals
  139. +static unsigned int Bm_next_signature = 0x1234;
  140. +static int bm_next_handle = 1;
  141. +int Bm_low_mem = 0;
  142. +// Bm_max_ram - How much RAM bmpman can use for textures.
  143. +// Set to <1 to make it use all it wants.
  144. +int Bm_max_ram = 0;        //16*1024*1024;         // Only use 16 MB for textures
  145. +static int Bm_ignore_duplicates = 0;
  146. +static int Bm_ignore_load_count = 0;
  147.  
  148. -const BM_TYPE bm_ani_type_list[] = { BM_TYPE_EFF, BM_TYPE_ANI };
  149. -const char *bm_ani_ext_list[] = { ".eff", ".ani" };
  150. -const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(bm_ani_type_list[0]);
  151. +#define EFF_FILENAME_CHECK { if ( be->type == BM_TYPE_EFF ) strcpy_s( filename, be->info.ani.eff.filename ); else strcpy_s( filename, be->filename ); }
  152.  
  153. -void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
  154. -void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
  155.  
  156. -// --------------------------------------------------------------------------------------------------------------------
  157. -// Declaration of protected variables (defined in cmdline.cpp).
  158. -extern int Cmdline_cache_bitmaps;
  159.  
  160. -// --------------------------------------------------------------------------------------------------------------------
  161. -// Definition of public variables (declared as extern in bm_internal.h).
  162. -bitmap_entry bm_bitmaps[MAX_BITMAPS];
  163. +// ===========================================
  164. +// Mode: 0 = High memory
  165. +//       1 = Low memory ( every other frame of ani's)
  166. +//       2 = Debug low memory ( only use first frame of each ani )
  167. +void bm_set_low_mem(int mode)
  168. +{
  169. +   Assert((mode >= 0) && (mode <= 2));
  170.  
  171. -// --------------------------------------------------------------------------------------------------------------------
  172. -// Definition of private variables at file scope (static).
  173. -static int bm_inited = 0;
  174. -static uint Bm_next_signature = 0x1234;
  175. -static int  bm_next_handle = 1;
  176. -static int Bm_low_mem = 0;
  177. +   CLAMP(mode, 0, 2);
  178. +   Bm_low_mem = mode;
  179. +}
  180.  
  181. -/**
  182. - * How much RAM bmpman can use for textures.
  183. - *
  184. - * @details Set to <1 to make it use all it wants.
  185. - *
  186. - * @note was initialized to 16*1024*1024 at some point to "use only 16MB for textures"
  187. - */
  188. -static int Bm_max_ram = 0;
  189.  
  190. -static int Bm_ignore_duplicates = 0;
  191. -static int Bm_ignore_load_count = 0;
  192. +int bm_get_next_handle()
  193. +{
  194. +   //bm_next_handle used to wrap around to 1 if it was over 30000. Now, believe it or not, but that is actually not uncommon;
  195. +   //as bitmaps get allocated and released, bm_next_handle could get there far more often than you'd think.
  196. +   //The check introduced below is intended to replace this behaviour with one that ensures we won't be seeing handle collisions
  197. +   //for a very long time.
  198. +
  199. +   bm_next_handle++;
  200.  
  201. -// --------------------------------------------------------------------------------------------------------------------
  202. -// Declaration of private functions and templates(declared as static type func(type param);)
  203. +   //Due to the way bm_next_handle is used to generate the /actual/ bitmap handles ( (bm_next_handle * MAX_BITMAPS) + free slot index in bm_bitmaps[]),
  204. +   //this check is necessary to ensure we don't start giving out negative handles all of a sudden.
  205. +   if (((bm_next_handle + 1) * MAX_BITMAPS) > INT_MAX)
  206. +       bm_next_handle = 1;
  207. +
  208. +   return bm_next_handle;
  209. +}
  210.  
  211. -bitmap_lookup::bitmap_lookup(int bitmap_num):
  212. -   Bitmap_data(NULL)
  213. +/**
  214. +* Frees a bitmaps data if it can
  215. +*/
  216. +static void bm_free_data(int n, bool release = false)
  217.  {
  218. -   if ( !bm_is_valid(bitmap_num) ) return;
  219. +   bitmap_entry *be;
  220. +   bitmap *bmp;
  221. +
  222. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  223. +
  224. +   be = &bm_bitmaps[n];
  225. +   bmp = &be->bm;
  226. +
  227. +   gr_bm_free_data(n, release);
  228. +
  229. +   // If there isn't a bitmap in this structure, don't
  230. +   // do anything but clear out the bitmap info
  231. +   if (be->type == BM_TYPE_NONE)
  232. +       goto SkipFree;
  233.  
  234. -   Num_channels = 3;
  235. +   // Don't free up memory for user defined bitmaps, since
  236. +   // BmpMan isn't the one in charge of allocating/deallocing them.
  237. +   if (be->type == BM_TYPE_USER) {
  238. +#ifdef BMPMAN_NDEBUG
  239. +       if (be->data_size != 0)
  240. +           bm_texture_ram -= be->data_size;
  241. +#endif
  242. +       goto SkipFree;
  243. +   }
  244.  
  245. -   if ( bm_has_alpha_channel(bitmap_num) ) {
  246. -       Num_channels = 4;
  247. +   // If this bitmap doesn't have any data to free, skip
  248. +   // the freeing it part of this.
  249. +   if (bmp->data == 0) {
  250. +#ifdef BMPMAN_NDEBUG
  251. +       if (be->data_size != 0)
  252. +           bm_texture_ram -= be->data_size;
  253. +#endif
  254. +       goto SkipFree;
  255.     }
  256.  
  257. -   int n = bitmap_num % MAX_BITMAPS;
  258. +   // Free up the data now!
  259. +#ifdef BMPMAN_NDEBUG
  260. +   bm_texture_ram -= be->data_size;
  261. +#endif
  262. +   vm_free((void *)bmp->data);
  263.  
  264. -   bitmap_entry *be = &bm_bitmaps[n];
  265. -  
  266. -   Width = be->bm.w;
  267. -   Height = be->bm.h;
  268. +   // reset the load_count to at least 1, don't do this in SkipFree though
  269. +   // since the real count ends up wrong
  270. +   be->load_count = 1;
  271.  
  272. -   Bitmap_data = (float*)vm_malloc(Width * Height * Num_channels * sizeof(float));
  273. +SkipFree:
  274.  
  275. -   gr_get_bitmap_from_texture((void*)Bitmap_data, bitmap_num);
  276. +   // Clear out & reset the bitmap data structure
  277. +   bmp->flags = 0;
  278. +   bmp->bpp = 0;
  279. +   bmp->data = 0;
  280. +   bmp->palette = NULL;
  281. +#ifdef BMPMAN_NDEBUG
  282. +   be->data_size = 0;
  283. +#endif
  284. +   be->signature = Bm_next_signature++;
  285.  }
  286.  
  287. -bitmap_lookup::~bitmap_lookup()
  288. +/**
  289. +* A special version of bm_free_data() that can be safely used in gr_*_texture
  290. +* to save system memory once textures have been transfered to API memory
  291. +* it doesn't restore the slot to a pristine state, it only releases the data
  292. +*
  293. +* NOTE: THIS SHOULD ONLY BE USED FROM bm_unload_fast()!!!
  294. +*/
  295. +static void bm_free_data_fast(int n)
  296.  {
  297. -   if ( Bitmap_data != NULL ) {
  298. -       vm_free(Bitmap_data);
  299. +   bitmap_entry *be;
  300. +   bitmap *bmp;
  301. +
  302. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  303. +
  304. +   be = &bm_bitmaps[n];
  305. +   bmp = &be->bm;
  306. +
  307. +   // If there isn't a bitmap in this structure, don't
  308. +   // do anything but clear out the bitmap info
  309. +   if (be->type == BM_TYPE_NONE)
  310. +       return;
  311. +
  312. +   // Don't free up memory for user defined bitmaps, since
  313. +   // BmpMan isn't the one in charge of allocating/deallocing them.
  314. +   if (be->type == BM_TYPE_USER) {
  315. +#ifdef BMPMAN_NDEBUG
  316. +       if (be->data_size != 0)
  317. +           bm_texture_ram -= be->data_size;
  318. +#endif
  319. +       return;
  320.     }
  321. -}
  322.  
  323. -bool bitmap_lookup::valid()
  324. -{
  325. -   return Bitmap_data != NULL;
  326. +   // If this bitmap doesn't have any data to free, skip
  327. +   // the freeing it part of this.
  328. +   if (bmp->data == 0) {
  329. +#ifdef BMPMAN_NDEBUG
  330. +       if (be->data_size != 0) {
  331. +           bm_texture_ram -= be->data_size;
  332. +           be->data_size = 0;
  333. +       }
  334. +#endif
  335. +       return;
  336. +   }
  337. +
  338. +   // Free up the data now!
  339. +#ifdef BMPMAN_NDEBUG
  340. +   bm_texture_ram -= be->data_size;
  341. +   be->data_size = 0;
  342. +#endif
  343. +   vm_free((void *)bmp->data);
  344. +   bmp->data = 0;
  345.  }
  346.  
  347. -float bitmap_lookup::map_texture_address(float address)
  348. +
  349. +void bm_clean_slot(int n)
  350.  {
  351. -   // assume we're just wrapping
  352. -   return address - floorf(address);
  353. +   bm_free_data(n);
  354.  }
  355.  
  356. -float bitmap_lookup::get_channel_red(float u, float v)
  357. +
  358. +void *bm_malloc(int n, int size)
  359.  {
  360. -   Assert( Bitmap_data != NULL );
  361. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  362.  
  363. -   CLAMP(u, 0.0, 1.0f);
  364. -   CLAMP(v, 0.0, 1.0f);
  365. +   if (size <= 0)
  366. +       return NULL;
  367.  
  368. -   int x = fl2i(map_texture_address(u) * (Width-1));
  369. -   int y = fl2i(map_texture_address(v) * (Height-1));
  370. +#ifdef BMPMAN_NDEBUG
  371. +   Assert(bm_bitmaps[n].data_size == 0);
  372. +   bm_bitmaps[n].data_size += size;
  373. +   bm_texture_ram += size;
  374. +#endif
  375.  
  376. -   return Bitmap_data[(y*Width + x)*Num_channels];
  377. +   return vm_malloc(size);
  378.  }
  379.  
  380. -float bitmap_lookup::get_channel_green(float u, float v)
  381. +/**
  382. +* Like bm_malloc but only keeps track of how much memory is getting used
  383. +*/
  384. +void bm_update_memory_used(int n, int size)
  385.  {
  386. -   Assert( Bitmap_data != NULL );
  387. -
  388. -   CLAMP(u, 0.0, 1.0f);
  389. -   CLAMP(v, 0.0, 1.0f);
  390. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  391. +   Assert(size >= 0);
  392.  
  393. -   int x = fl2i(map_texture_address(u) * (Width-1));
  394. -   int y = fl2i(map_texture_address(v) * (Height-1));
  395. +#ifdef BMPMAN_NDEBUG
  396. +   Assert(bm_bitmaps[n].data_size == 0);
  397. +   bm_bitmaps[n].data_size += size;
  398. +   bm_texture_ram += size;
  399. +#endif
  400. +}
  401.  
  402. -   return Bitmap_data[(y*Width + x)*Num_channels + 1];
  403. +void bm_close()
  404. +{
  405. +   int i;
  406. +   if (bm_inited) {
  407. +       for (i = 0; i<MAX_BITMAPS; i++) {
  408. +           bm_free_data(i);            // clears flags, bbp, data, etc
  409. +       }
  410. +       bm_inited = 0;
  411. +   }
  412.  }
  413.  
  414. -float bitmap_lookup::get_channel_blue(float u, float v)
  415. +void bm_init()
  416.  {
  417. -   Assert( Bitmap_data != NULL );
  418. +   int i;
  419.  
  420. -   int x = fl2i(map_texture_address(u) * (Width-1));
  421. -   int y = fl2i(map_texture_address(v) * (Height-1));
  422. +   mprintf(("Size of bitmap info = %d KB\n", sizeof(bm_bitmaps) / 1024));
  423. +   mprintf(("Size of bitmap extra info = %d bytes\n", sizeof(bm_extra_info)));
  424.  
  425. -   return Bitmap_data[(y*Width + x)*Num_channels + 2];
  426. -}
  427. +   if (!bm_inited) {
  428. +       bm_inited = 1;
  429. +       atexit(bm_close);
  430. +   }
  431.  
  432. -float bitmap_lookup::get_channel_alpha(float u, float v)
  433. -{
  434. -   Assert( Bitmap_data != NULL );
  435. +   for (i = 0; i<MAX_BITMAPS; i++) {
  436. +       bm_bitmaps[i].filename[0] = '\0';
  437. +       bm_bitmaps[i].type = BM_TYPE_NONE;
  438. +       bm_bitmaps[i].comp_type = BM_TYPE_NONE;
  439. +       bm_bitmaps[i].dir_type = CF_TYPE_ANY;
  440. +       bm_bitmaps[i].info.user.data = NULL;
  441. +       bm_bitmaps[i].mem_taken = 0;
  442. +       bm_bitmaps[i].bm.data = 0;
  443. +       bm_bitmaps[i].bm.palette = NULL;
  444. +       bm_bitmaps[i].info.ani.eff.type = BM_TYPE_NONE;
  445. +       bm_bitmaps[i].info.ani.eff.filename[0] = '\0';
  446. +#ifdef BMPMAN_NDEBUG
  447. +       bm_bitmaps[i].data_size = 0;
  448. +       bm_bitmaps[i].used_count = 0;
  449. +       bm_bitmaps[i].used_last_frame = 0;
  450. +       bm_bitmaps[i].used_this_frame = 0;
  451. +#endif
  452. +       bm_bitmaps[i].load_count = 0;
  453.  
  454. -   int x = fl2i(map_texture_address(u) * (Width-1));
  455. -   int y = fl2i(map_texture_address(v) * (Height-1));
  456. +       gr_bm_init(i);
  457.  
  458. -   return Bitmap_data[(y*Width + x)*Num_channels + 3];
  459. +       bm_free_data(i);    // clears flags, bbp, data, etc
  460. +   }
  461.  }
  462.  
  463.  /**
  464. - * Converts the bitmap referenced by bmp to the type specified by flags
  465. - */
  466. -static void bm_convert_format(bitmap *bmp, ubyte flags);
  467. +* Returns number of bytes of bitmaps locked this frame
  468. +* @param ntotal    number of bytes of bitmaps locked this frame
  469. +* @param nnew      number of bytes of bitmaps locked this frame that weren't locked last frame
  470. +*/
  471. +void bm_get_frame_usage(int *ntotal, int *nnew)
  472. +{
  473. +#ifdef BMPMAN_NDEBUG
  474. +   int i;
  475.  
  476. -/**
  477. - * Frees a bitmap's data if it can
  478. - */
  479. -static void bm_free_data(int n, bool release = false);
  480. +   *ntotal = 0;
  481. +   *nnew = 0;
  482.  
  483. -/**
  484. - * A special version of bm_free_data() that can be safely used in gr_*_texture
  485. - * to save system memory once textures have been transfered to API memory
  486. - * it doesn't restore the slot to a pristine state, it only releases the data
  487. - *
  488. - * @attention: THIS SHOULD ONLY BE USED FROM bm_unload_fast()!!!
  489. - */
  490. -static void bm_free_data_fast(int n);
  491. +   for (i = 0; i<MAX_BITMAPS; i++) {
  492. +       if ((bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].used_this_frame)) {
  493. +           if (!bm_bitmaps[i].used_last_frame) {
  494. +               *nnew += bm_bitmaps[i].mem_taken;
  495. +           }
  496. +           *ntotal += bm_bitmaps[i].mem_taken;
  497. +       }
  498. +       bm_bitmaps[i].used_last_frame = bm_bitmaps[i].used_this_frame;
  499. +       bm_bitmaps[i].used_this_frame = 0;
  500. +   }
  501. +#endif
  502. +}
  503.  
  504.  /**
  505. - * Given a raw filename and an extension set, try and find the bitmap
  506. - * that isn't already loaded and may exist somewhere on the disk
  507. - *
  508. - * @returns -1 if it could not be found,
  509. - * @returns index into ext_list[] if it was found as a file, fills img_cfg if available
  510. - */
  511. -static int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp = NULL, int dir_type = CF_TYPE_ANY);
  512. +* Creates a bitmap that exists in RAM somewhere, instead
  513. +* of coming from a disk file.
  514. +*
  515. +* You pass in a pointer to a block of 32 (or 8)-bit-per-pixel data.
  516. +* Right now, the only bpp you can pass in is 32 or 8.
  517. +*
  518. +* On success, it returns the bitmap number.
  519. +*
  520. +* You cannot free that RAM until bm_release is called on that bitmap.
  521. +*/
  522. +int bm_create(int bpp, int w, int h, void *data, int flags)
  523. +{
  524. +   if (bpp == 8) {
  525. +       Assert(flags & BMP_AABITMAP);
  526. +   }
  527. +   else {
  528. +       Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
  529. +   }
  530.  
  531. -/**
  532. - * Given a raw filename, try and find a bitmap that's already loaded
  533. - *
  534. - * @returns 0 if it could not be found,
  535. - * @returns 1 if it already exists, fills in handle
  536. - */
  537. -static int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type = CF_TYPE_ANY, bool animated_type = false);
  538. -
  539. -/**
  540. - * Finds a block of... something
  541. - *
  542. - * @returns -1 if the block could not be found
  543. - * @returns the handle of the block ?
  544. - */
  545. -static int find_block_of(int n);
  546. -
  547. -// --------------------------------------------------------------------------------------------------------------------
  548. -// Macro-defined functions
  549. -
  550. -DCF(bm_frag, "Shows BmpMan fragmentation") {
  551. -   if (dc_optional_string_either("help", "--help")) {
  552. -       dc_printf("Displays a graphic showing the BmpMan fragmentation. Color key:\n");
  553. -       dc_printf("\tGray  : NONE\n");
  554. -       dc_printf("\tRed   : PCXn");
  555. -       dc_printf("\tGreen : USER, TGA, PNG, DDS, other\n");
  556. -       dc_printf("\tBlue  : ANI, EFF\n\n");
  557. -
  558. -       dc_printf("Once done reviewing the graphic, press any key to return to the console\n");
  559. -       return;
  560. -   }
  561. -
  562. -   gr_clear();
  563. -
  564. -   int x = 0, y = 0;
  565. -   int xs = 2, ys = 2;
  566. -   int w = 4, h = 4;
  567. -
  568. -   for (int i = 0; i<MAX_BITMAPS; i++) {
  569. -       switch (bm_bitmaps[i].type) {
  570. -       case BM_TYPE_NONE:
  571. -           gr_set_color(128, 128, 128);
  572. -           break;
  573. -       case BM_TYPE_PCX:
  574. -           gr_set_color(255, 0, 0);
  575. -           break;
  576. -       case BM_TYPE_USER:
  577. -       case BM_TYPE_TGA:
  578. -       case BM_TYPE_PNG:
  579. -       case BM_TYPE_DDS:
  580. -           gr_set_color(0, 255, 0);
  581. -           break;
  582. -       case BM_TYPE_ANI:
  583. -       case BM_TYPE_EFF:
  584. -           gr_set_color(0, 0, 255);
  585. -           break;
  586. -       default:
  587. -           gr_set_color(0, 255, 0);
  588. -           break;
  589. -       }
  590. -
  591. -       gr_rect(x + xs, y + ys, w, h);
  592. -       x += w + xs + xs;
  593. -       if (x > 639) {
  594. -           x = 0;
  595. -           y += h + ys + ys;
  596. -       }
  597. -   }
  598. -
  599. -   gr_flip();
  600. -   key_getch();
  601. -}
  602. -
  603. -DCF(bmpman, "Shows/changes bitmap caching parameters and usage") {
  604. -   if (dc_optional_string_either("help", "--help")) {
  605. -       dc_printf("Usage: BmpMan [arg]\nWhere arg can be any of the following:\n");
  606. -       dc_printf("\tflush    Unloads all bitmaps.\n");
  607. -       dc_printf("\tram [x]  Sets max mem usage to x MB. (Set to 0 to have no limit.)\n");
  608. -       dc_printf("\t?        Displays status of Bitmap manager.\n");
  609. -       return;
  610. -   }
  611. -
  612. -   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  613. -       dc_printf("Total RAM usage: %d bytes\n", bm_texture_ram);
  614. -
  615. -       if (Bm_max_ram > 1024 * 1024) {
  616. -           dc_printf("\tMax RAM allowed: %.1f MB\n", i2fl(Bm_max_ram) / (1024.0f*1024.0f));
  617. -       } else if (Bm_max_ram > 1024) {
  618. -           dc_printf("\tMax RAM allowed: %.1f KB\n", i2fl(Bm_max_ram) / (1024.0f));
  619. -       } else if (Bm_max_ram > 0) {
  620. -           dc_printf("\tMax RAM allowed: %d bytes\n", Bm_max_ram);
  621. -       } else {
  622. -           dc_printf("\tNo RAM limit\n");
  623. -       }
  624. -       return;
  625. -   }
  626. -
  627. -
  628. -   if (dc_optional_string("flush")) {
  629. -       dc_printf("Total RAM usage before flush: %d bytes\n", bm_texture_ram);
  630. -       int i;
  631. -       for (i = 0; i < MAX_BITMAPS; i++) {
  632. -           if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  633. -               bm_free_data(i);
  634. -           }
  635. -       }
  636. -       dc_printf("Total RAM after flush: %d bytes\n", bm_texture_ram);
  637. -   } else if (dc_optional_string("ram")) {
  638. -       dc_stuff_int(&Bm_max_ram);
  639. -
  640. -       if (Bm_max_ram > 0) {
  641. -           dc_printf("BmpMan limited to %i, MB's\n", Bm_max_ram);
  642. -           Bm_max_ram *= 1024 * 1024;
  643. -       } else if (Bm_max_ram == 0) {
  644. -           dc_printf("!!BmpMan memory is unlimited!!\n");
  645. -       } else {
  646. -           dc_printf("Illegal value. Must be non-negative.");
  647. -       }
  648. -   } else {
  649. -       dc_printf("<BmpMan> No argument given\n");
  650. -   }
  651. -}
  652. -
  653. -DCF(bmpslots, "Writes bitmap slot info to fs2_open.log") {
  654. -   if (dc_optional_string_either("help", "--help")) {
  655. -       dc_printf("Usage: bmpslots\n");
  656. -       dc_printf("\tWrites bitmap slot info to fs2_open.log\n");
  657. -       return;
  658. -   }
  659. -   bm_print_bitmaps();
  660. -}
  661. -
  662. -// --------------------------------------------------------------------------------------------------------------------
  663. -// Definition of all functions, in alphabetical order
  664. -void bm_clean_slot(int n) {
  665. -   bm_free_data(n);
  666. -}
  667. -
  668. -void bm_close() {
  669. -   int i;
  670. -   if (bm_inited) {
  671. -       for (i = 0; i<MAX_BITMAPS; i++) {
  672. -           bm_free_data(i);            // clears flags, bbp, data, etc
  673. -       }
  674. -       bm_inited = 0;
  675. -   }
  676. -}
  677. -
  678. -int bm_create(int bpp, int w, int h, void *data, int flags) {
  679. -   if (bpp == 8) {
  680. -       Assert(flags & BMP_AABITMAP);
  681. -   } else {
  682. -       Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
  683. -   }
  684. -
  685. -   if (!bm_inited) bm_init();
  686. +   if (!bm_inited) bm_init();
  687.  
  688.     int n = -1;
  689.  
  690. @@ -424,526 +405,482 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
  691.  
  692.     bm_bitmaps[n].load_count++;
  693.  
  694. -   bm_update_memory_used(n, (int)bm_bitmaps[n].mem_taken);
  695. +   bm_update_memory_used(n, bm_bitmaps[n].mem_taken);
  696.  
  697.     gr_bm_create(n);
  698.  
  699.     return bm_bitmaps[n].handle;
  700.  }
  701.  
  702. -void bm_convert_format(bitmap *bmp, ubyte flags) {
  703. -   int idx;
  704. +/**
  705. +* Given a raw filename and an extension set, try and find the bitmap
  706. +* that isn't already loaded and may exist somewhere on the disk
  707. +*
  708. +* @return  -1 if it could not be found index into ext_list[] if it was found as a file, fills img_cfg if available
  709. +*/
  710. +int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp = NULL, int dir_type = CF_TYPE_ANY)
  711. +{
  712. +   char full_path[MAX_PATH];
  713. +   int size = 0, offset = 0;
  714. +   int rval = -1;
  715.  
  716. -   // no transparency for 24 bpp images
  717. -   if (!(flags & BMP_AABITMAP) && (bmp->bpp == 24))
  718. -       return;
  719. +   rval = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, sizeof(full_path) - 1, full_path, &size, &offset, 0);
  720.  
  721. -   if (Is_standalone) {
  722. -       Assert(bmp->bpp == 8);
  723. -       return;
  724. -   } else {
  725. -       if (flags & BMP_AABITMAP)
  726. -           Assert(bmp->bpp == 8);
  727. -       else
  728. -           Assert((bmp->bpp == 16) || (bmp->bpp == 32));
  729. -   }
  730. +   // could not be found, or is invalid for some reason
  731. +   if ((rval < 0) || (rval >= num_ext))
  732. +       return -1;
  733.  
  734. -   // maybe swizzle to be an xparent texture
  735. -   if (!(bmp->flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_XPARENT)) {
  736. -       for (idx = 0; idx<bmp->w*bmp->h; idx++) {
  737. -           // if the pixel is transparent
  738. -           if (((ushort*)bmp->data)[idx] == Gr_t_green.mask) {
  739. -               ((ushort*)bmp->data)[idx] = 0;
  740. -           }
  741. -       }
  742. +   CFILE *test = cfopen_special(full_path, "rb", size, offset, dir_type);
  743.  
  744. -       bmp->flags |= BMP_TEX_XPARENT;
  745. +   if (test != NULL) {
  746. +       if (img_cfp != NULL)
  747. +           *img_cfp = test;
  748. +
  749. +       return rval;
  750.     }
  751. +
  752. +   // umm, that's not good...
  753. +   return -1;
  754.  }
  755.  
  756. -void bm_free_data(int n, bool release)
  757. +/**
  758. +* Given a raw filename, try and find a bitmap that's already loaded
  759. +* @return  0 if it could not be found, 1 if it already exists, fills in handle
  760. +*/
  761. +int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type = CF_TYPE_ANY, bool animated_type = false)
  762.  {
  763. -   bitmap_entry *be;
  764. -   bitmap *bmp;
  765. +   if (Bm_ignore_duplicates)
  766. +       return 0;
  767.  
  768. -   Assert( (n >= 0) && (n < MAX_BITMAPS) );
  769. +   int i;
  770.  
  771. -   be = &bm_bitmaps[n];
  772. -   bmp = &be->bm;
  773. +   for (i = 0; i < MAX_BITMAPS; i++) {
  774. +       if (bm_bitmaps[i].type == BM_TYPE_NONE)
  775. +           continue;
  776.  
  777. -   gr_bm_free_data(n, release);
  778. +       if (bm_bitmaps[i].dir_type != dir_type)
  779. +           continue;
  780.  
  781. -   // If there isn't a bitmap in this structure, don't
  782. -   // do anything but clear out the bitmap info
  783. -   if (be->type==BM_TYPE_NONE)
  784. -       goto SkipFree;
  785. +       bool animated = ((bm_bitmaps[i].type == BM_TYPE_EFF) || (bm_bitmaps[i].type == BM_TYPE_ANI));
  786.  
  787. -   // Don't free up memory for user defined bitmaps, since
  788. -   // BmpMan isn't the one in charge of allocating/deallocing them.
  789. -   if (be->type==BM_TYPE_USER) {
  790. -#ifdef BMPMAN_NDEBUG
  791. -       if ( be->data_size != 0 )
  792. -           bm_texture_ram -= be->data_size;
  793. -#endif
  794. -       goto SkipFree;
  795. -   }
  796. +       if (animated_type && !animated)
  797. +           continue;
  798. +       else if (!animated_type && animated)
  799. +           continue;
  800.  
  801. -   // If this bitmap doesn't have any data to free, skip
  802. -   // the freeing it part of this.
  803. -   if (bmp->data == 0) {
  804. -#ifdef BMPMAN_NDEBUG
  805. -       if ( be->data_size != 0 )
  806. -           bm_texture_ram -= be->data_size;
  807. -#endif
  808. -       goto SkipFree;
  809. +       if (!strextcmp(real_filename, bm_bitmaps[i].filename)) {
  810. +           nprintf(("BmpFastLoad", "Found bitmap %s -- number %d\n", bm_bitmaps[i].filename, i));
  811. +           bm_bitmaps[i].load_count++;
  812. +           *handle = bm_bitmaps[i].handle;
  813. +           return 1;
  814. +       }
  815.     }
  816.  
  817. -   // Free up the data now!
  818. -#ifdef BMPMAN_NDEBUG
  819. -   bm_texture_ram -= be->data_size;
  820. -#endif
  821. -   vm_free((void *)bmp->data);
  822. -
  823. -   // reset the load_count to at least 1, don't do this in SkipFree though
  824. -   // since the real count ends up wrong
  825. -   be->load_count = 1;
  826. -
  827. -SkipFree:
  828. -
  829. -   // Clear out & reset the bitmap data structure
  830. -   bmp->flags = 0;
  831. -   bmp->bpp = 0;
  832. -   bmp->data = 0;
  833. -   bmp->palette = NULL;
  834. -#ifdef BMPMAN_NDEBUG
  835. -   be->data_size = 0;
  836. -#endif
  837. -   be->signature = Bm_next_signature++;
  838. +   // not found to be loaded already
  839. +   return 0;
  840.  }
  841.  
  842. -void bm_free_data_fast(int n)
  843. +/**
  844. +* Loads a bitmap so we can draw with it later.
  845. +* Function doesn't actually load the data, only width, height, and possibly flags.
  846. +*
  847. +* @return A negative number if it couldn't load the bitmap.
  848. +* @return On success, it returns the bitmap number.
  849. +*/
  850. +int bm_load(const char *real_filename)
  851.  {
  852. -   bitmap_entry *be;
  853. -   bitmap *bmp;
  854. +   int i, id = -1, free_slot = -1;
  855. +   int w, h, bpp = 8;
  856. +   int rc = 0;
  857. +   int bm_size = 0, mm_lvl = 0;
  858. +   char filename[MAX_FILENAME_LEN];
  859. +   ubyte type = BM_TYPE_NONE;
  860. +   ubyte c_type = BM_TYPE_NONE;
  861. +   CFILE *img_cfp = NULL;
  862. +   int handle = -1;
  863.  
  864. -   Assert( (n >= 0) && (n < MAX_BITMAPS) );
  865. +   if (!bm_inited)
  866. +       bm_init();
  867.  
  868. -   be = &bm_bitmaps[n];
  869. -   bmp = &be->bm;
  870. +   // if no file was passed then get out now
  871. +   if ((real_filename == NULL) || (strlen(real_filename) <= 0))
  872. +       return -1;
  873.  
  874. -   // If there isn't a bitmap in this structure, don't
  875. -   // do anything but clear out the bitmap info
  876. -   if (be->type == BM_TYPE_NONE)
  877. -       return;
  878. +   // make sure no one passed an extension
  879. +   memset(filename, 0, MAX_FILENAME_LEN);
  880. +   strncpy(filename, real_filename, MAX_FILENAME_LEN - 1);
  881. +   char *p = strrchr(filename, '.');
  882. +   if (p) {
  883. +       mprintf(("Someone passed an extension to bm_load for file '%s'\n", real_filename));
  884. +       *p = 0;
  885. +   }
  886.  
  887. -   // Don't free up memory for user defined bitmaps, since
  888. -   // BmpMan isn't the one in charge of allocating/deallocing them.
  889. -   if (be->type == BM_TYPE_USER) {
  890. -#ifdef BMPMAN_NDEBUG
  891. -       if ( be->data_size != 0 )
  892. -           bm_texture_ram -= be->data_size;
  893. -#endif
  894. -       return;
  895. +   // If we are standalone server keep replacing the 'right_bracket' (right side help bracket) as the filename
  896. +   // should keep the game happy while loading only single pcx file which the needs to be present in any case
  897. +   if (Is_standalone) {
  898. +       char standalone_filename[MAX_FILENAME_LEN] = "right_bracket";
  899. +       strcpy_s(filename, standalone_filename);
  900.     }
  901.  
  902. -   // If this bitmap doesn't have any data to free, skip
  903. -   // the freeing it part of this.
  904. -   if (bmp->data == 0) {
  905. -#ifdef BMPMAN_NDEBUG
  906. -       if ( be->data_size != 0 ) {
  907. -           bm_texture_ram -= be->data_size;
  908. -           be->data_size = 0;
  909. -       }
  910. -#endif
  911. -       return;
  912. +   // safety catch for strcat...
  913. +   // MAX_FILENAME_LEN-5 == '.' plus 3 letter ext plus NULL terminator
  914. +   if (strlen(filename) > MAX_FILENAME_LEN - 5) {
  915. +       Warning(LOCATION, "Passed filename, '%s', is too long to support an extension!!\n\nMaximum length, minus the extension, is %i characters.\n", filename, MAX_FILENAME_LEN - 5);
  916. +       return -1;
  917.     }
  918.  
  919. -   // Free up the data now!
  920. -#ifdef BMPMAN_NDEBUG
  921. -   bm_texture_ram -= be->data_size;
  922. -   be->data_size = 0;
  923. -#endif
  924. -   vm_free((void *)bmp->data);
  925. -   bmp->data = 0;
  926. -}
  927. +   // Lets find out what type it is
  928. +   {
  929. +       const int NUM_TYPES = 5;
  930. +       const ubyte type_list[NUM_TYPES] = { BM_TYPE_DDS, BM_TYPE_TGA, BM_TYPE_PNG, BM_TYPE_JPG, BM_TYPE_PCX };
  931. +       const char *ext_list[NUM_TYPES] = { ".dds", ".tga", ".png", ".jpg", ".pcx" };
  932.  
  933. -int bm_get_cache_slot(int bitmap_id, int separate_ani_frames) {
  934. -   int n = bitmap_id % MAX_BITMAPS;
  935. +       // see if it's already loaded (checks for any type with filename)
  936. +       if (bm_load_sub_fast(filename, &handle))
  937. +           return handle;
  938.  
  939. -   Assert(n >= 0);
  940. -   Assert(bm_bitmaps[n].handle == bitmap_id);      // INVALID BITMAP HANDLE
  941. +       // if we are still here then we need to fall back to a file-based search
  942. +       int rval = bm_load_sub_slow(filename, NUM_TYPES, ext_list, &img_cfp);
  943.  
  944. -   bitmap_entry    *be = &bm_bitmaps[n];
  945. +       if (rval < 0)
  946. +           return -1;
  947.  
  948. -   if ((!separate_ani_frames) && ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF))) {
  949. -       return be->info.ani.first_frame;
  950. +       strcat_s(filename, ext_list[rval]);
  951. +       type = type_list[rval];
  952.     }
  953.  
  954. -   return n;
  955. -
  956. -}
  957. -
  958. -void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) {
  959. -   int bit_32 = 0;
  960. -
  961. -   if ((gr_screen.bits_per_pixel == 32) && (Gr_current_red == &Gr_red)) {
  962. -       bit_32 = 1;
  963. -   }
  964. +   Assert(type != BM_TYPE_NONE);
  965.  
  966. -   if (r != NULL) {
  967. -       if (bit_32) {
  968. -           *r = ubyte(((*((unsigned int*)pixel) & Gr_current_red->mask) >> Gr_current_red->shift)*Gr_current_red->scale);
  969. -       } else {
  970. -           *r = ubyte(((((unsigned short*)pixel)[0] & Gr_current_red->mask) >> Gr_current_red->shift)*Gr_current_red->scale);
  971. +   // Find an open slot
  972. +   for (i = 0; i < MAX_BITMAPS; i++) {
  973. +       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  974. +           free_slot = i;
  975. +           break;
  976.         }
  977.     }
  978.  
  979. -   if (g != NULL) {
  980. -       if (bit_32) {
  981. -           *g = ubyte(((*((unsigned int*)pixel) & Gr_current_green->mask) >> Gr_current_green->shift)*Gr_current_green->scale);
  982. -       } else {
  983. -           *g = ubyte(((((unsigned short*)pixel)[0] & Gr_current_green->mask) >> Gr_current_green->shift)*Gr_current_green->scale);
  984. -       }
  985. +   if (free_slot < 0) {
  986. +       Assertion(free_slot < 0, "Could not find free BMPMAN slot for bitmap: %s", real_filename);
  987. +       goto Done;
  988.     }
  989.  
  990. -   if (b != NULL) {
  991. -       if (bit_32) {
  992. -           *b = ubyte(((*((unsigned int*)pixel) & Gr_current_blue->mask) >> Gr_current_blue->shift)*Gr_current_blue->scale);
  993. -       } else {
  994. -           *b = ubyte(((((unsigned short*)pixel)[0] & Gr_current_blue->mask) >> Gr_current_blue->shift)*Gr_current_blue->scale);
  995. -       }
  996. -   }
  997. +   rc = gr_bm_load(type, free_slot, filename, img_cfp, &w, &h, &bpp, &c_type, &mm_lvl, &bm_size);
  998.  
  999. -   // get the alpha value
  1000. -   if (a != NULL) {
  1001. -       *a = 1;
  1002. +   if (rc != 0)
  1003. +       goto Done;
  1004.  
  1005. -       Assert(!bit_32);
  1006. -       if (!(((unsigned short*)pixel)[0] & 0x8000)) {
  1007. -           *a = 0;
  1008. -       }
  1009. -   }
  1010. -}
  1011. +   if ((bm_size <= 0) && (w) && (h) && (bpp))
  1012. +       bm_size = (w * h * (bpp >> 3));
  1013.  
  1014. -const char *bm_get_filename(int handle) {
  1015. -   int n;
  1016.  
  1017. -   n = handle % MAX_BITMAPS;
  1018. -   Assert(bm_bitmaps[n].handle == handle);     // INVALID BITMAP HANDLE
  1019. -   return bm_bitmaps[n].filename;
  1020. -}
  1021. +   handle = bm_get_next_handle() * MAX_BITMAPS + free_slot;
  1022.  
  1023. -void bm_get_filename(int bitmapnum, char *filename) {
  1024. -   if (!bm_is_valid(bitmapnum)) {
  1025. -       strcpy(filename, "");
  1026. -       return;
  1027. -   }
  1028. +   // ensure fields are cleared out from previous bitmap
  1029. +   memset(&bm_bitmaps[free_slot], 0, sizeof(bitmap_entry));
  1030.  
  1031. -   int n = bitmapnum % MAX_BITMAPS;
  1032. +   // Mark the slot as filled, because cf_read might load a new bitmap
  1033. +   // into this slot.
  1034. +   strncpy(bm_bitmaps[free_slot].filename, filename, MAX_FILENAME_LEN - 1);
  1035. +   bm_bitmaps[free_slot].id = id;
  1036. +   bm_bitmaps[free_slot].type = type;
  1037. +   bm_bitmaps[free_slot].comp_type = c_type;
  1038. +   bm_bitmaps[free_slot].signature = Bm_next_signature++;
  1039. +   bm_bitmaps[free_slot].bm.w = (short)w;
  1040. +   bm_bitmaps[free_slot].bm.rowsize = (short)w;
  1041. +   bm_bitmaps[free_slot].bm.h = (short)h;
  1042. +   bm_bitmaps[free_slot].bm.bpp = 0;
  1043. +   bm_bitmaps[free_slot].bm.true_bpp = (ubyte)bpp;
  1044. +   bm_bitmaps[free_slot].bm.flags = 0;
  1045. +   bm_bitmaps[free_slot].bm.data = 0;
  1046. +   bm_bitmaps[free_slot].bm.palette = NULL;
  1047. +   bm_bitmaps[free_slot].num_mipmaps = mm_lvl;
  1048. +   bm_bitmaps[free_slot].mem_taken = bm_size;
  1049. +   bm_bitmaps[free_slot].dir_type = CF_TYPE_ANY;
  1050. +   bm_bitmaps[free_slot].palette_checksum = 0;
  1051. +   bm_bitmaps[free_slot].handle = handle;
  1052. +   bm_bitmaps[free_slot].last_used = -1;
  1053.  
  1054. -   Assert(n >= 0);
  1055. +   bm_bitmaps[free_slot].load_count++;
  1056. +Done:
  1057. +   if (img_cfp != NULL)
  1058. +       cfclose(img_cfp);
  1059.  
  1060. -   // return filename
  1061. -   strcpy(filename, bm_bitmaps[n].filename);
  1062. +   return handle;
  1063.  }
  1064.  
  1065. -void bm_get_frame_usage(int *ntotal, int *nnew) {
  1066. -#ifdef BMPMAN_NDEBUG
  1067. -   int i;
  1068. +/**
  1069. +* Same as bm_load above, just with an SCP_string
  1070. +*/
  1071. +int bm_load(const SCP_string& filename)
  1072. +{
  1073. +   return bm_load(filename.c_str());
  1074. +}
  1075.  
  1076. -   *ntotal = 0;
  1077. -   *nnew = 0;
  1078. +/**
  1079. +* Special load function. Basically allows you to load a bitmap which already exists (by filename).
  1080. +*
  1081. +* This is useful because in some cases we need to have a bitmap which is locked in screen format
  1082. +* _and_ texture format, such as pilot pics and squad logos
  1083. +*/
  1084. +int bm_load_duplicate(const char *filename)
  1085. +{
  1086. +   int ret;
  1087.  
  1088. -   for (i = 0; i<MAX_BITMAPS; i++) {
  1089. -       if ((bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].used_this_frame)) {
  1090. -           if (!bm_bitmaps[i].used_last_frame) {
  1091. -               *nnew += (int)bm_bitmaps[i].mem_taken;
  1092. -           }
  1093. -           *ntotal += (int)bm_bitmaps[i].mem_taken;
  1094. -       }
  1095. -       bm_bitmaps[i].used_last_frame = bm_bitmaps[i].used_this_frame;
  1096. -       bm_bitmaps[i].used_this_frame = 0;
  1097. -   }
  1098. -#endif
  1099. +   // ignore duplicates
  1100. +   Bm_ignore_duplicates = 1;
  1101. +
  1102. +   // load
  1103. +   ret = bm_load(filename);
  1104. +
  1105. +   // back to normal
  1106. +   Bm_ignore_duplicates = 0;
  1107. +
  1108. +   return ret;
  1109.  }
  1110.  
  1111. -int bm_get_info(int handle, int *w, int * h, ubyte * flags, int *nframes, int *fps) {
  1112. -   bitmap * bmp;
  1113. +/**
  1114. +* This function is used to reload a different bitmap into an existing slot.
  1115. +* This should only be used if you are certain the new picture has the same type, dimensions etc.
  1116. +*
  1117. +* @return negative if the given handle doesn't exist, the filename was empty or the slot is still locked
  1118. +* @return the bitmap_handle on success
  1119. +*/
  1120. +int bm_reload(int bitmap_handle, const char* filename)
  1121. +{
  1122. +   if (!bm_inited)
  1123. +       bm_init();
  1124.  
  1125. -   if (!bm_inited) return -1;
  1126. +   // if no file was passed then get out now
  1127. +   if ((filename == NULL) || (strlen(filename) <= 0))
  1128. +       return -1;
  1129.  
  1130. -   int bitmapnum = handle % MAX_BITMAPS;
  1131. +   int bitmapnum = bitmap_handle % MAX_BITMAPS;
  1132.  
  1133. -#ifndef NDEBUG
  1134. -   if (bm_bitmaps[bitmapnum].handle != handle) {
  1135. -       mprintf(("bm_get_info - %s: bm_bitmaps[%d].handle = %d, handle = %d\n", bm_bitmaps[bitmapnum].filename, bitmapnum, bm_bitmaps[bitmapnum].handle, handle));
  1136. +   if (bm_bitmaps[bitmapnum].type == BM_TYPE_NONE)
  1137. +       return -1;
  1138. +
  1139. +   if (bm_bitmaps[bitmapnum].ref_count)
  1140. +   {
  1141. +       nprintf(("BmpMan", "Trying to reload a bitmap that is still locked. Filename: %s, ref_count: %d", bm_bitmaps[bitmapnum].filename, bm_bitmaps[bitmapnum].ref_count));
  1142. +       return -1;
  1143.     }
  1144. -#endif
  1145.  
  1146. -   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_info().\nThis might be due to an invalid animation somewhere else.\n", handle);        // INVALID BITMAP HANDLE!
  1147. +   strcpy_s(bm_bitmaps[bitmapnum].filename, filename);
  1148. +   return bitmap_handle;
  1149. +}
  1150.  
  1151. -   if ((bm_bitmaps[bitmapnum].type == BM_TYPE_NONE) || (bm_bitmaps[bitmapnum].handle != handle)) {
  1152. -       if (w) *w = 0;
  1153. -       if (h) *h = 0;
  1154. -       if (flags) *flags = 0;
  1155. -       if (nframes) *nframes = 0;
  1156. -       if (fps) *fps = 0;
  1157. -       return -1;
  1158. +DCF(bm_frag, "Shows BmpMan fragmentation")
  1159. +{
  1160. +   if (dc_optional_string_either("help", "--help")) {
  1161. +       dc_printf("Displays a graphic showing the BmpMan fragmentation. Color key:\n");
  1162. +       dc_printf("\tGray  : NONE\n");
  1163. +       dc_printf("\tRed   : PCXn");
  1164. +       dc_printf("\tGreen : USER, TGA, PNG, DDS\n");
  1165. +       dc_printf("\tBlue  : ANI, EFF\n\n");
  1166. +
  1167. +       dc_printf("Once done reviewing the graphic, press any key to return to the console\n");
  1168. +       return;
  1169.     }
  1170.  
  1171. -   bmp = &(bm_bitmaps[bitmapnum].bm);
  1172. +   gr_clear();
  1173.  
  1174. -   if (w) *w = bmp->w;
  1175. -   if (h) *h = bmp->h;
  1176. -   if (flags) *flags = bmp->flags;
  1177. +   int x = 0, y = 0;
  1178. +   int xs = 2, ys = 2;
  1179. +   int w = 4, h = 4;
  1180.  
  1181. -   if ((bm_bitmaps[bitmapnum].type == BM_TYPE_ANI) || (bm_bitmaps[bitmapnum].type == BM_TYPE_EFF)) {
  1182. -       if (nframes) {
  1183. -           *nframes = bm_bitmaps[bitmapnum].info.ani.num_frames;
  1184. -       }
  1185. -       if (fps) {
  1186. -           *fps = bm_bitmaps[bitmapnum].info.ani.fps;
  1187. +   for (int i = 0; i<MAX_BITMAPS; i++) {
  1188. +       switch (bm_bitmaps[i].type) {
  1189. +       case BM_TYPE_NONE:
  1190. +           gr_set_color(128, 128, 128);
  1191. +           break;
  1192. +       case BM_TYPE_PCX:
  1193. +           gr_set_color(255, 0, 0);
  1194. +           break;
  1195. +       case BM_TYPE_USER:
  1196. +       case BM_TYPE_TGA:
  1197. +       case BM_TYPE_PNG:
  1198. +       case BM_TYPE_DDS:
  1199. +           gr_set_color(0, 255, 0);
  1200. +           break;
  1201. +       case BM_TYPE_ANI:
  1202. +       case BM_TYPE_EFF:
  1203. +           gr_set_color(0, 0, 255);
  1204. +           break;
  1205.         }
  1206.  
  1207. -       return bm_bitmaps[bm_bitmaps[bitmapnum].info.ani.first_frame].handle;
  1208. -   } else {
  1209. -       if (nframes) {
  1210. -           *nframes = 1;
  1211. -       }
  1212. -       if (fps) {
  1213. -           *fps = 0;
  1214. +       gr_rect(x + xs, y + ys, w, h);
  1215. +       x += w + xs + xs;
  1216. +       if (x > 639) {
  1217. +           x = 0;
  1218. +           y += h + ys + ys;
  1219.         }
  1220. -
  1221. -       return handle;
  1222.     }
  1223. +
  1224. +   gr_flip();
  1225. +   key_getch();
  1226.  }
  1227.  
  1228. -int bm_get_next_handle() {
  1229. -   //bm_next_handle used to wrap around to 1 if it was over 30000. Now, believe it or not, but that is actually not uncommon;
  1230. -   //as bitmaps get allocated and released, bm_next_handle could get there far more often than you'd think.
  1231. -   //The check introduced below is intended to replace this behaviour with one that ensures we won't be seeing handle collisions
  1232. -   //for a very long time.
  1233. -
  1234. -   bm_next_handle++;
  1235. +static int find_block_of(int n)
  1236. +{
  1237. +   int i, cnt = 0, nstart = 0;
  1238.  
  1239. -   //Due to the way bm_next_handle is used to generate the /actual/ bitmap handles ( (bm_next_handle * MAX_BITMAPS) + free slot index in bm_bitmaps[]),
  1240. -   //this check is necessary to ensure we don't start giving out negative handles all of a sudden.
  1241. -   if ((bm_next_handle + 1) > INT_MAX / MAX_BITMAPS) {
  1242. -       bm_next_handle = 1;
  1243. -       mprintf(("BMPMAN: bitmap handles wrapped back to 1\n"));
  1244. +   if (n < 1) {
  1245. +       Int3();
  1246. +       return -1;
  1247.     }
  1248.  
  1249. -   return bm_next_handle;
  1250. -}
  1251. -
  1252. -int bm_get_num_mipmaps(int num) {
  1253. -   int n = num % MAX_BITMAPS;
  1254. -
  1255. -   Assert(n >= 0);
  1256. -   Assert(num == bm_bitmaps[n].handle);
  1257. -
  1258. -   if (bm_bitmaps[n].num_mipmaps == 0)
  1259. -       return 1;
  1260. -
  1261. -   return bm_bitmaps[n].num_mipmaps;
  1262. -}
  1263. -
  1264. -void bm_get_palette(int handle, ubyte *pal, char *name) {
  1265. -   char *filename;
  1266. -   int w, h;
  1267. -
  1268. -   int n = handle % MAX_BITMAPS;
  1269. -   Assert(bm_bitmaps[n].handle == handle);     // INVALID BITMAP HANDLE
  1270. -
  1271. -   filename = bm_bitmaps[n].filename;
  1272. +   for (i = 0; i < MAX_BITMAPS; i++) {
  1273. +       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  1274. +           if (cnt == 0)
  1275. +               nstart = i;
  1276.  
  1277. -   if (name) {
  1278. -       strcpy(name, filename);
  1279. -   }
  1280. +           cnt++;
  1281. +       }
  1282. +       else {
  1283. +           cnt = 0;
  1284. +       }
  1285.  
  1286. -   int pcx_error = pcx_read_header(filename, NULL, &w, &h, NULL, pal);
  1287. -   if (pcx_error != PCX_ERROR_NONE) {
  1288. -       // Error(LOCATION, "Couldn't open '%s'\n", filename );
  1289. +       if (cnt == n)
  1290. +           return nstart;
  1291.     }
  1292. -}
  1293. -
  1294. -uint bm_get_signature(int handle) {
  1295. -   if (!bm_inited) bm_init();
  1296. -
  1297. -   int bitmapnum = handle % MAX_BITMAPS;
  1298. -   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_signature().\nThis might be due to an invalid animation somewhere else.\n", handle);       // INVALID BITMAP HANDLE!
  1299. -
  1300. -   return bm_bitmaps[bitmapnum].signature;
  1301. -}
  1302.  
  1303. -size_t bm_get_size(int handle) {
  1304. -   int n = handle % MAX_BITMAPS;
  1305. -
  1306. -   Assert(n >= 0);
  1307. -   Assert(handle == bm_bitmaps[n].handle);
  1308. -
  1309. -   return bm_bitmaps[n].mem_taken;
  1310. +   return -1;
  1311.  }
  1312.  
  1313. -int bm_get_tcache_type(int num) {
  1314. -   if (bm_is_compressed(num))
  1315. -       return TCACHE_TYPE_COMPRESSED;
  1316. -
  1317. -   return TCACHE_TYPE_NORMAL;
  1318. -}
  1319. +int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type)
  1320. +{
  1321. +   int frames = 0, fps = 30, keyframe = 0, rval;
  1322. +   char ext[8];
  1323. +   ubyte c_type = BM_TYPE_NONE;
  1324. +   char file_text[1024];
  1325. +   char file_text_raw[1024];
  1326.  
  1327. -BM_TYPE bm_get_type(int handle) {
  1328. -   if (!bm_inited) bm_init();
  1329. +   memset(ext, 0, sizeof(ext));
  1330. +   memset(file_text, 0, sizeof(file_text));
  1331. +   memset(file_text_raw, 0, sizeof(file_text_raw));
  1332.  
  1333. -   int bitmapnum = handle % MAX_BITMAPS;
  1334. -   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_type().\nThis might be due to an invalid animation somewhere else.\n", handle);        // INVALID BITMAP HANDLE!
  1335. +   // pause anything that may happen to be parsing right now
  1336. +   pause_parse();
  1337.  
  1338. -   return bm_bitmaps[bitmapnum].type;
  1339. -}
  1340. +   if ((rval = setjmp(parse_abort)) != 0) {
  1341. +       mprintf(("BMPMAN: Unable to parse '%s'!  Error code = %i.\n", filename, rval));
  1342. +       unpause_parse();
  1343. +       return -1;
  1344. +   }
  1345.  
  1346. -bool bm_has_alpha_channel(int handle) {
  1347. -   int n = handle % MAX_BITMAPS;
  1348. +   // now start parsing the EFF
  1349. +   read_file_text(filename, dir_type, file_text, file_text_raw);
  1350. +   reset_parse(file_text);
  1351.  
  1352. -   Assert(n >= 0);
  1353. -   Assert(handle == bm_bitmaps[n].handle);
  1354. +   required_string("$Type:");
  1355. +   stuff_string(ext, F_NAME, sizeof(ext));
  1356.  
  1357. -   // assume that PCX never has a real alpha channel (it may be 32-bit, but without any alpha)
  1358. -   if (bm_bitmaps[n].type == BM_TYPE_PCX)
  1359. -       return 0;
  1360. +   required_string("$Frames:");
  1361. +   stuff_int(&frames);
  1362.  
  1363. -   return (bm_bitmaps[n].bm.true_bpp == 32);
  1364. -}
  1365. +   if (optional_string("$FPS:"))
  1366. +       stuff_int(&fps);
  1367.  
  1368. -void bm_init() {
  1369. -   int i;
  1370. +   if (optional_string("$Keyframe:"))
  1371. +       stuff_int(&keyframe);
  1372.  
  1373. -   mprintf(("Size of bitmap info = " SIZE_T_ARG " KB\n", sizeof(bm_bitmaps) / 1024));
  1374. -   mprintf(("Size of bitmap extra info = " SIZE_T_ARG " bytes\n", sizeof(bm_extra_info)));
  1375. +   // done with EFF so unpause parsing so whatever can continue
  1376. +   unpause_parse();
  1377.  
  1378. -   if (!bm_inited) {
  1379. -       bm_inited = 1;
  1380. -       atexit(bm_close);
  1381. +   if (!stricmp(NOX("dds"), ext)) {
  1382. +       c_type = BM_TYPE_DDS;
  1383.     }
  1384. -
  1385. -   for (i = 0; i<MAX_BITMAPS; i++) {
  1386. -       bm_bitmaps[i].filename[0] = '\0';
  1387. -       bm_bitmaps[i].type = BM_TYPE_NONE;
  1388. -       bm_bitmaps[i].comp_type = BM_TYPE_NONE;
  1389. -       bm_bitmaps[i].dir_type = CF_TYPE_ANY;
  1390. -       bm_bitmaps[i].info.user.data = NULL;
  1391. -       bm_bitmaps[i].mem_taken = 0;
  1392. -       bm_bitmaps[i].bm.data = 0;
  1393. -       bm_bitmaps[i].bm.palette = NULL;
  1394. -       bm_bitmaps[i].info.ani.eff.type = BM_TYPE_NONE;
  1395. -       bm_bitmaps[i].info.ani.eff.filename[0] = '\0';
  1396. -#ifdef BMPMAN_NDEBUG
  1397. -       bm_bitmaps[i].data_size = 0;
  1398. -       bm_bitmaps[i].used_count = 0;
  1399. -       bm_bitmaps[i].used_last_frame = 0;
  1400. -       bm_bitmaps[i].used_this_frame = 0;
  1401. -#endif
  1402. -       bm_bitmaps[i].load_count = 0;
  1403. -
  1404. -       gr_bm_init(i);
  1405. -
  1406. -       bm_free_data(i);    // clears flags, bbp, data, etc
  1407. +   else if (!stricmp(NOX("tga"), ext)) {
  1408. +       c_type = BM_TYPE_TGA;
  1409.     }
  1410. -}
  1411. -
  1412. -int bm_is_compressed(int num) {
  1413. -   int n = num % MAX_BITMAPS;
  1414. -   BM_TYPE type = BM_TYPE_NONE;
  1415. -
  1416. -   //duh
  1417. -   if (!Use_compressed_textures)
  1418. -       return 0;
  1419. -
  1420. -   Assert(n >= 0);
  1421. -   Assert(num == bm_bitmaps[n].handle);
  1422. -
  1423. -   type = bm_bitmaps[n].comp_type;
  1424. -
  1425. -   switch (type) {
  1426. -   case BM_TYPE_NONE:
  1427. -   case BM_TYPE_DDS:
  1428. -       return 0;
  1429. -
  1430. -   case BM_TYPE_DXT1:
  1431. -       return DDS_DXT1;
  1432. -
  1433. -   case BM_TYPE_DXT3:
  1434. -       return DDS_DXT3;
  1435. -
  1436. -   case BM_TYPE_DXT5:
  1437. -       return DDS_DXT5;
  1438. -
  1439. -   case BM_TYPE_CUBEMAP_DXT1:
  1440. -       return DDS_CUBEMAP_DXT1;
  1441. -
  1442. -   case BM_TYPE_CUBEMAP_DXT3:
  1443. -       return DDS_CUBEMAP_DXT3;
  1444. -
  1445. -   case BM_TYPE_CUBEMAP_DXT5:
  1446. -       return DDS_CUBEMAP_DXT5;
  1447. -
  1448. -   default:
  1449. -       return 0;
  1450. +   else if (!stricmp(NOX("png"), ext)) {
  1451. +       c_type = BM_TYPE_PNG;
  1452. +   }
  1453. +   else if (!stricmp(NOX("jpg"), ext)) {
  1454. +       c_type = BM_TYPE_JPG;
  1455. +   }
  1456. +   else if (!stricmp(NOX("pcx"), ext)) {
  1457. +       c_type = BM_TYPE_PCX;
  1458. +   }
  1459. +   else {
  1460. +       mprintf(("BMPMAN: Unknown file type in EFF parse!\n"));
  1461. +       return -1;
  1462.     }
  1463. -}
  1464.  
  1465. -int bm_is_render_target(int bitmap_id) {
  1466. -   int n = bitmap_id % MAX_BITMAPS;
  1467. +   // did we do anything?
  1468. +   if (c_type == BM_TYPE_NONE || frames == 0) {
  1469. +       mprintf(("BMPMAN: EFF parse ERROR!\n"));
  1470. +       return -1;
  1471. +   }
  1472.  
  1473. -   Assert(n >= 0);
  1474. -   Assert(bitmap_id == bm_bitmaps[n].handle);
  1475. +   if (type)
  1476. +       *type = c_type;
  1477.  
  1478. -   if (!((bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC) || (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  1479. -       return 0;
  1480. -   }
  1481. +   if (nframes)
  1482. +       *nframes = frames;
  1483.  
  1484. -   return bm_bitmaps[n].type;
  1485. -}
  1486. +   if (nfps)
  1487. +       *nfps = fps;
  1488.  
  1489. -int bm_is_valid(int handle) {
  1490. -   // Ensure that certain known false or out of range handles are quickly returned as invalid,
  1491. -   // prior to utilising the handle in a way which leads to memory access outside bm_bitmaps[]
  1492. -   if (!bm_inited) return 0;
  1493. -   if (handle < 0) return 0;
  1494. +   if (key)
  1495. +       *key = keyframe;
  1496.  
  1497. -   return (bm_bitmaps[handle % MAX_BITMAPS].handle == handle);
  1498. +   return 0;
  1499.  }
  1500.  
  1501. -int bm_load(const char *real_filename) {
  1502. -   int i, free_slot = -1;
  1503. -   int w, h, bpp = 8;
  1504. -   int rc = 0;
  1505. -   int bm_size = 0, mm_lvl = 0;
  1506. +/**
  1507. +* Load animation
  1508. +*
  1509. +* @param real_filename     filename of animation
  1510. +* @param nframes           OUTPUT parameter:   number of frames in the animation
  1511. +* @param fps               OUTPUT/OPTIONAL parameter: intended fps for the animation
  1512. +* @param keyframe          Keyframe number
  1513. +* @param can_drop_frames   Toggle to allow dropped frames
  1514. +* @param dir_type          Directory type
  1515. +*
  1516. +* @returns Bitmap number of first frame in the animation
  1517. +*/
  1518. +int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
  1519. +{
  1520. +   int i, n;
  1521. +   anim    the_anim;
  1522. +   CFILE   *img_cfp = NULL;
  1523.     char filename[MAX_FILENAME_LEN];
  1524. -   BM_TYPE type = BM_TYPE_NONE;
  1525. -   BM_TYPE c_type = BM_TYPE_NONE;
  1526. -   CFILE *img_cfp = NULL;
  1527. -   int handle = -1;
  1528. +   int reduced = 0;
  1529. +   int anim_fps = 0, anim_frames = 0, key = 0;
  1530. +   int anim_width = 0, anim_height = 0;
  1531. +   ubyte type = BM_TYPE_NONE, eff_type = BM_TYPE_NONE, c_type = BM_TYPE_NONE;
  1532. +   int bpp = 0, mm_lvl = 0, img_size = 0;
  1533. +   char clean_name[MAX_FILENAME_LEN];
  1534. +   const int NUM_TYPES = 2;
  1535. +   const ubyte type_list[NUM_TYPES] = { BM_TYPE_EFF, BM_TYPE_ANI };
  1536. +   const char *ext_list[NUM_TYPES] = { ".eff", ".ani" };
  1537.  
  1538.     if (!bm_inited)
  1539.         bm_init();
  1540.  
  1541. -   // if no file was passed then get out now
  1542. -   if ((real_filename == NULL) || (strlen(real_filename) <= 0))
  1543. -       return -1;
  1544. +   // set defaults for frame count and fps before going any further
  1545. +   if (nframes)
  1546. +       *nframes = 0;
  1547. +
  1548. +   if (fps)
  1549. +       *fps = 0;
  1550. +
  1551. +   if (keyframe)
  1552. +       *keyframe = 0;
  1553.  
  1554. -   // make sure no one passed an extension
  1555.     memset(filename, 0, MAX_FILENAME_LEN);
  1556.     strncpy(filename, real_filename, MAX_FILENAME_LEN - 1);
  1557. -   char *p = strrchr(filename, '.');
  1558. +   char *p = strchr(filename, '.');
  1559.     if (p) {
  1560. -       mprintf(("Someone passed an extension to bm_load for file '%s'\n", real_filename));
  1561. +       mprintf(("Someone passed an extension to bm_load_animation for file '%s'\n", real_filename));
  1562.         *p = 0;
  1563.     }
  1564.  
  1565. -   // If we are standalone server keep replacing the 'right_bracket' (right side help bracket) as the filename
  1566. -   // should keep the game happy while loading only single pcx file which the needs to be present in any case
  1567. +   // If we are standalone server keep replacing the 'cursorweb' (mouse cursor) as the filename
  1568. +   // should keep the game happy while loading only single ani file which the needs to be present in any case
  1569.     if (Is_standalone) {
  1570. -       char standalone_filename[MAX_FILENAME_LEN] = "right_bracket";
  1571. +       char standalone_filename[MAX_FILENAME_LEN] = "cursorweb";
  1572.         strcpy_s(filename, standalone_filename);
  1573.     }
  1574.  
  1575. @@ -954,224 +891,20 @@ int bm_load(const char *real_filename) {
  1576.         return -1;
  1577.     }
  1578.  
  1579. +   // used later if EFF type
  1580. +   strcpy_s(clean_name, filename);
  1581. +
  1582.     // Lets find out what type it is
  1583.     {
  1584. -       // see if it's already loaded (checks for any type with filename)
  1585. -       if (bm_load_sub_fast(filename, &handle))
  1586. -           return handle;
  1587. +       int handle = -1;
  1588.  
  1589. -       // if we are still here then we need to fall back to a file-based search
  1590. -       int rval = bm_load_sub_slow(filename, BM_NUM_TYPES, bm_ext_list, &img_cfp);
  1591. +       // do a search for any previously loaded files (looks at filename only)
  1592. +       if (bm_load_sub_fast(filename, &handle, dir_type, true)) {
  1593. +           n = handle % MAX_BITMAPS;
  1594. +           Assert(bm_bitmaps[n].handle == handle);
  1595.  
  1596. -       if (rval < 0)
  1597. -           return -1;
  1598. -
  1599. -       strcat_s(filename, bm_ext_list[rval]);
  1600. -       type = bm_type_list[rval];
  1601. -   }
  1602. -
  1603. -   Assert(type != BM_TYPE_NONE);
  1604. -
  1605. -   // Find an open slot
  1606. -   for (i = 0; i < MAX_BITMAPS; i++) {
  1607. -       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  1608. -           free_slot = i;
  1609. -           break;
  1610. -       }
  1611. -   }
  1612. -
  1613. -   if (free_slot < 0) {
  1614. -       Assertion(free_slot < 0, "Could not find free BMPMAN slot for bitmap: %s", real_filename);
  1615. -       goto Done;
  1616. -   }
  1617. -
  1618. -   rc = gr_bm_load(type, free_slot, filename, img_cfp, &w, &h, &bpp, &c_type, &mm_lvl, &bm_size);
  1619. -
  1620. -   if (rc != 0)
  1621. -       goto Done;
  1622. -
  1623. -   if ((bm_size <= 0) && (w) && (h) && (bpp))
  1624. -       bm_size = (w * h * (bpp >> 3));
  1625. -
  1626. -
  1627. -   handle = bm_get_next_handle() * MAX_BITMAPS + free_slot;
  1628. -
  1629. -   // ensure fields are cleared out from previous bitmap
  1630. -   memset(&bm_bitmaps[free_slot], 0, sizeof(bitmap_entry));
  1631. -
  1632. -   // Mark the slot as filled, because cf_read might load a new bitmap
  1633. -   // into this slot.
  1634. -   strncpy(bm_bitmaps[free_slot].filename, filename, MAX_FILENAME_LEN - 1);
  1635. -   bm_bitmaps[free_slot].type = type;
  1636. -   bm_bitmaps[free_slot].comp_type = c_type;
  1637. -   bm_bitmaps[free_slot].signature = Bm_next_signature++;
  1638. -   bm_bitmaps[free_slot].bm.w = (short)w;
  1639. -   bm_bitmaps[free_slot].bm.rowsize = (short)w;
  1640. -   bm_bitmaps[free_slot].bm.h = (short)h;
  1641. -   bm_bitmaps[free_slot].bm.bpp = 0;
  1642. -   bm_bitmaps[free_slot].bm.true_bpp = (ubyte)bpp;
  1643. -   bm_bitmaps[free_slot].bm.flags = 0;
  1644. -   bm_bitmaps[free_slot].bm.data = 0;
  1645. -   bm_bitmaps[free_slot].bm.palette = NULL;
  1646. -   bm_bitmaps[free_slot].num_mipmaps = mm_lvl;
  1647. -   bm_bitmaps[free_slot].mem_taken = (size_t)bm_size;
  1648. -   bm_bitmaps[free_slot].dir_type = CF_TYPE_ANY;
  1649. -   bm_bitmaps[free_slot].palette_checksum = 0;
  1650. -   bm_bitmaps[free_slot].handle = handle;
  1651. -   bm_bitmaps[free_slot].last_used = -1;
  1652. -
  1653. -   bm_bitmaps[free_slot].load_count++;
  1654. -
  1655. -Done:
  1656. -   if (img_cfp != NULL)
  1657. -       cfclose(img_cfp);
  1658. -
  1659. -   return handle;
  1660. -}
  1661. -
  1662. -int bm_load(const SCP_string& filename) {
  1663. -   return bm_load(filename.c_str());
  1664. -}
  1665. -
  1666. -bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type) {
  1667. -   int frames = 0, fps = 30, keyframe = 0;
  1668. -   char ext[8];
  1669. -   BM_TYPE c_type = BM_TYPE_NONE;
  1670. -   char file_text[1024];
  1671. -   char file_text_raw[1024];
  1672. -
  1673. -   memset(ext, 0, sizeof(ext));
  1674. -   memset(file_text, 0, sizeof(file_text));
  1675. -   memset(file_text_raw, 0, sizeof(file_text_raw));
  1676. -
  1677. -   // pause anything that may happen to be parsing right now
  1678. -   pause_parse();
  1679. -
  1680. -   try
  1681. -   {
  1682. -       // now start parsing the EFF
  1683. -       read_file_text(filename, dir_type, file_text, file_text_raw);
  1684. -       reset_parse(file_text);
  1685. -
  1686. -       required_string("$Type:");
  1687. -       stuff_string(ext, F_NAME, sizeof(ext));
  1688. -
  1689. -       required_string("$Frames:");
  1690. -       stuff_int(&frames);
  1691. -
  1692. -       if (optional_string("$FPS:"))
  1693. -           stuff_int(&fps);
  1694. -
  1695. -       if (optional_string("$Keyframe:"))
  1696. -           stuff_int(&keyframe);
  1697. -   }
  1698. -   catch (const parse::ParseException& e)
  1699. -   {
  1700. -       mprintf(("BMPMAN: Unable to parse '%s'!  Error message = %s.\n", filename, e.what()));
  1701. -       unpause_parse();
  1702. -       return false;
  1703. -   }
  1704. -
  1705. -   // done with EFF so unpause parsing so whatever can continue
  1706. -   unpause_parse();
  1707. -
  1708. -   if (!stricmp(NOX("dds"), ext)) {
  1709. -       c_type = BM_TYPE_DDS;
  1710. -   } else if (!stricmp(NOX("tga"), ext)) {
  1711. -       c_type = BM_TYPE_TGA;
  1712. -   } else if (!stricmp(NOX("png"), ext)) {
  1713. -       c_type = BM_TYPE_PNG;
  1714. -   } else if (!stricmp(NOX("jpg"), ext)) {
  1715. -       c_type = BM_TYPE_JPG;
  1716. -   } else if (!stricmp(NOX("pcx"), ext)) {
  1717. -       c_type = BM_TYPE_PCX;
  1718. -   } else {
  1719. -       mprintf(("BMPMAN: Unknown file type in EFF parse!\n"));
  1720. -       return false;
  1721. -   }
  1722. -
  1723. -   // did we do anything?
  1724. -   if (c_type == BM_TYPE_NONE || frames == 0) {
  1725. -       mprintf(("BMPMAN: EFF parse ERROR!\n"));
  1726. -       return false;
  1727. -   }
  1728. -
  1729. -   if (type)
  1730. -       *type = c_type;
  1731. -
  1732. -   if (nframes)
  1733. -       *nframes = frames;
  1734. -
  1735. -   if (nfps)
  1736. -       *nfps = fps;
  1737. -
  1738. -   if (key)
  1739. -       *key = keyframe;
  1740. -
  1741. -   return true;
  1742. -}
  1743. -
  1744. -int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type) {
  1745. -   int i, n;
  1746. -   anim    the_anim;
  1747. -   CFILE   *img_cfp = NULL;
  1748. -   char filename[MAX_FILENAME_LEN];
  1749. -   int reduced = 0;
  1750. -   int anim_fps = 0, anim_frames = 0, key = 0;
  1751. -   int anim_width = 0, anim_height = 0;
  1752. -   BM_TYPE type = BM_TYPE_NONE, eff_type = BM_TYPE_NONE, c_type = BM_TYPE_NONE;
  1753. -   int bpp = 0, mm_lvl = 0, img_size = 0;
  1754. -   char clean_name[MAX_FILENAME_LEN];
  1755. -
  1756. -   if (!bm_inited)
  1757. -       bm_init();
  1758. -
  1759. -   // set defaults for frame count and fps before going any further
  1760. -   if (nframes)
  1761. -       *nframes = 0;
  1762. -
  1763. -   if (fps)
  1764. -       *fps = 0;
  1765. -
  1766. -   if (keyframe)
  1767. -       *keyframe = 0;
  1768. -
  1769. -   memset(filename, 0, MAX_FILENAME_LEN);
  1770. -   strncpy(filename, real_filename, MAX_FILENAME_LEN - 1);
  1771. -   char *p = strchr(filename, '.');
  1772. -   if (p) {
  1773. -       mprintf(("Someone passed an extension to bm_load_animation for file '%s'\n", real_filename));
  1774. -       *p = 0;
  1775. -   }
  1776. -
  1777. -   // If we are standalone server keep replacing the 'cursorweb' (mouse cursor) as the filename
  1778. -   // should keep the game happy while loading only single ani file which the needs to be present in any case
  1779. -   if (Is_standalone) {
  1780. -       char standalone_filename[MAX_FILENAME_LEN] = "cursorweb";
  1781. -       strcpy_s(filename, standalone_filename);
  1782. -   }
  1783. -
  1784. -   // safety catch for strcat...
  1785. -   // MAX_FILENAME_LEN-5 == '.' plus 3 letter ext plus NULL terminator
  1786. -   if (strlen(filename) > MAX_FILENAME_LEN - 5) {
  1787. -       Warning(LOCATION, "Passed filename, '%s', is too long to support an extension!!\n\nMaximum length, minus the extension, is %i characters.\n", filename, MAX_FILENAME_LEN - 5);
  1788. -       return -1;
  1789. -   }
  1790. -
  1791. -   // used later if EFF type
  1792. -   strcpy_s(clean_name, filename);
  1793. -
  1794. -   // Lets find out what type it is
  1795. -   {
  1796. -       int handle = -1;
  1797. -
  1798. -       // do a search for any previously loaded files (looks at filename only)
  1799. -       if (bm_load_sub_fast(filename, &handle, dir_type, true)) {
  1800. -           n = handle % MAX_BITMAPS;
  1801. -           Assert(bm_bitmaps[n].handle == handle);
  1802. -
  1803. -           if (nframes)
  1804. -               *nframes = bm_bitmaps[n].info.ani.num_frames;
  1805. +           if (nframes)
  1806. +               *nframes = bm_bitmaps[n].info.ani.num_frames;
  1807.  
  1808.             if (fps)
  1809.                 *fps = bm_bitmaps[n].info.ani.fps;
  1810. @@ -1183,13 +916,13 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1811.         }
  1812.  
  1813.         // if we are still here then we need to fall back to a file-based search
  1814. -       int rval = bm_load_sub_slow(filename, BM_ANI_NUM_TYPES, bm_ani_ext_list, &img_cfp, dir_type);
  1815. +       int rval = bm_load_sub_slow(filename, NUM_TYPES, ext_list, &img_cfp, dir_type);
  1816.  
  1817.         if (rval < 0)
  1818.             return -1;
  1819.  
  1820. -       strcat_s(filename, bm_ani_ext_list[rval]);
  1821. -       type = bm_ani_type_list[rval];
  1822. +       strcat_s(filename, ext_list[rval]);
  1823. +       type = type_list[rval];
  1824.     }
  1825.  
  1826.     // If we found an animation then there is an extra 5 char size limit to adhere to. We don't do this check earlier since it's only needed if we found an anim
  1827. @@ -1204,10 +937,11 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1828.  
  1829.     // it's an effect file, any readable image type with eff being txt
  1830.     if (type == BM_TYPE_EFF) {
  1831. -       if (!bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type)) {
  1832. +       if (bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type) != 0) {
  1833.             mprintf(("BMPMAN: Error reading EFF\n"));
  1834.             return -1;
  1835. -       } else {
  1836. +       }
  1837. +       else {
  1838.             mprintf(("BMPMAN: Found EFF (%s) with %d frames at %d fps.\n", filename, anim_frames, anim_fps));
  1839.         }
  1840.     }
  1841. @@ -1232,7 +966,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1842.             the_anim.keys = (key_frame*)vm_malloc(sizeof(key_frame) * the_anim.num_keys);
  1843.             Assert(the_anim.keys != NULL);
  1844.  
  1845. -           for (i = 0; i<the_anim.num_keys; i++) {
  1846. +           for (i = 0;i<the_anim.num_keys;i++) {
  1847.                 the_anim.keys[i].frame_num = 0;
  1848.                 cfread(&the_anim.keys[i].frame_num, 2, 1, img_cfp);
  1849.                 cfread(&the_anim.keys[i].offset, 4, 1, img_cfp);
  1850. @@ -1241,11 +975,9 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1851.             }
  1852.             //some retail anis have their keyframes reversed
  1853.             key = MAX(the_anim.keys[0].frame_num, the_anim.keys[1].frame_num);
  1854. -          
  1855. -           vm_free(the_anim.keys);
  1856. -           the_anim.keys = nullptr;
  1857.         }
  1858. -   } else {
  1859. +   }
  1860. +   else {
  1861.         return -1;
  1862.     }
  1863.  
  1864. @@ -1254,7 +986,8 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1865.             reduced = 1;
  1866.             anim_frames = (anim_frames + 1) / 2;
  1867.             anim_fps = (anim_fps / 2);
  1868. -       } else if (Bm_low_mem == 2) {
  1869. +       }
  1870. +       else if (Bm_low_mem == 2) {
  1871.             anim_frames = 1;
  1872.         }
  1873.     }
  1874. @@ -1271,6 +1004,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1875.  
  1876.     int first_handle = bm_get_next_handle();
  1877.  
  1878. +   Assert(strlen(filename) < MAX_FILENAME_LEN);
  1879.     for (i = 0; i < anim_frames; i++) {
  1880.         memset(&bm_bitmaps[n + i], 0, sizeof(bitmap_entry));
  1881.  
  1882. @@ -1331,14 +1065,15 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1883.         bm_bitmaps[n + i].handle = first_handle*MAX_BITMAPS + n + i;
  1884.         bm_bitmaps[n + i].last_used = -1;
  1885.         bm_bitmaps[n + i].num_mipmaps = mm_lvl;
  1886. -       bm_bitmaps[n + i].mem_taken = (size_t)img_size;
  1887. +       bm_bitmaps[n + i].mem_taken = img_size;
  1888.         bm_bitmaps[n + i].dir_type = dir_type;
  1889.  
  1890.         bm_bitmaps[n + i].load_count++;
  1891.  
  1892.         if (i == 0) {
  1893.             sprintf(bm_bitmaps[n + i].filename, "%s", filename);
  1894. -       } else {
  1895. +       }
  1896. +       else {
  1897.             sprintf(bm_bitmaps[n + i].filename, "%s[%d]", filename, i);
  1898.         }
  1899.  
  1900. @@ -1359,28 +1094,15 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
  1901.     return bm_bitmaps[n].handle;
  1902.  }
  1903.  
  1904. -int bm_load_duplicate(const char *filename) {
  1905. -   int ret;
  1906. -
  1907. -   // ignore duplicates
  1908. -   Bm_ignore_duplicates = 1;
  1909. -
  1910. -   // load
  1911. -   ret = bm_load(filename);
  1912. -
  1913. -   // back to normal
  1914. -   Bm_ignore_duplicates = 0;
  1915. -
  1916. -   return ret;
  1917. -}
  1918. -
  1919. -int bm_load_either(const char *filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type) {
  1920. +int bm_load_either(const char *filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
  1921. +{
  1922.     if (nframes != NULL)
  1923.         *nframes = 0;
  1924.     if (fps != NULL)
  1925.         *fps = 0;
  1926.     int tidx = bm_load_animation(filename, nframes, fps, keyframe, can_drop_frames, dir_type);
  1927. -   if (tidx == -1) {
  1928. +   if (tidx == -1)
  1929. +   {
  1930.         tidx = bm_load(filename);
  1931.         if (tidx != -1 && nframes != NULL)
  1932.             *nframes = 1;
  1933. @@ -1389,161 +1111,181 @@ int bm_load_either(const char *filename, int *nframes, int *fps, int *keyframe,
  1934.     return tidx;
  1935.  }
  1936.  
  1937. -int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type, bool animated_type) {
  1938. -   if (Bm_ignore_duplicates)
  1939. -       return 0;
  1940. -
  1941. -   int i;
  1942. +/**
  1943. +* Sanity check to ensure invalid bitmap handles are picked up early
  1944. +*
  1945. +* Some early known false or out of range handles (such as negative) are checked within
  1946. +* an initial routine pass, followed by a more thorough check routine to ensure the
  1947. +* series of bitmaps within the bm_bitmaps[] structure have not become invalid.
  1948. +*
  1949. +* @param handle Bitmap handle to check for validity
  1950. +* @return 1 for valid, 0 for invalid
  1951. +*/
  1952. +int bm_is_valid(int handle)
  1953. +{
  1954. +   // Ensure that certain known false or out of range handles are quickly returned as invalid,
  1955. +   // prior to utilising the handle in a way which leads to memory access outside bm_bitmaps[]
  1956. +   if (!bm_inited) return 0;
  1957. +   if (handle < 0) return 0;
  1958.  
  1959. -   for (i = 0; i < MAX_BITMAPS; i++) {
  1960. -       if (bm_bitmaps[i].type == BM_TYPE_NONE)
  1961. -           continue;
  1962. +   return (bm_bitmaps[handle % MAX_BITMAPS].handle == handle);
  1963. +}
  1964.  
  1965. -       if (bm_bitmaps[i].dir_type != dir_type)
  1966. -           continue;
  1967. +/**
  1968. +* Gets info.
  1969. +* w,h,flags,nframes or fps can be NULL if you don't care.
  1970. +*/
  1971. +int bm_get_info(int handle, int *w, int * h, ubyte * flags, int *nframes, int *fps)
  1972. +{
  1973. +   bitmap * bmp;
  1974.  
  1975. -       bool animated = ((bm_bitmaps[i].type == BM_TYPE_EFF) || (bm_bitmaps[i].type == BM_TYPE_ANI));
  1976. +   if (!bm_inited) return -1;
  1977.  
  1978. -       if (animated_type && !animated)
  1979. -           continue;
  1980. -       else if (!animated_type && animated)
  1981. -           continue;
  1982. +   int bitmapnum = handle % MAX_BITMAPS;
  1983.  
  1984. -       if (!strextcmp(real_filename, bm_bitmaps[i].filename)) {
  1985. -           nprintf(("BmpFastLoad", "Found bitmap %s -- number %d\n", bm_bitmaps[i].filename, i));
  1986. -           bm_bitmaps[i].load_count++;
  1987. -           *handle = bm_bitmaps[i].handle;
  1988. -           return 1;
  1989. -       }
  1990. +#ifndef NDEBUG
  1991. +   if (bm_bitmaps[bitmapnum].handle != handle) {
  1992. +       mprintf(("bm_get_info - %s: bm_bitmaps[%d].handle = %d, handle = %d\n", bm_bitmaps[bitmapnum].filename, bitmapnum, bm_bitmaps[bitmapnum].handle, handle));
  1993.     }
  1994. +#endif
  1995.  
  1996. -   // not found to be loaded already
  1997. -   return 0;
  1998. -}
  1999. -
  2000. -int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp, int dir_type) {
  2001. -   char full_path[MAX_PATH];
  2002. -   int size = 0, offset = 0;
  2003. -   int rval = -1;
  2004. -
  2005. -   rval = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, sizeof(full_path) - 1, full_path, &size, &offset, 0);
  2006. +   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_info().\nThis might be due to an invalid animation somewhere else.\n", handle);        // INVALID BITMAP HANDLE!
  2007.  
  2008. -   // could not be found, or is invalid for some reason
  2009. -   if ((rval < 0) || (rval >= num_ext))
  2010. +   if ((bm_bitmaps[bitmapnum].type == BM_TYPE_NONE) || (bm_bitmaps[bitmapnum].handle != handle)) {
  2011. +       if (w) *w = 0;
  2012. +       if (h) *h = 0;
  2013. +       if (flags) *flags = 0;
  2014. +       if (nframes) *nframes = 0;
  2015. +       if (fps) *fps = 0;
  2016.         return -1;
  2017. +   }
  2018.  
  2019. -   CFILE *test = cfopen_special(full_path, "rb", size, offset, dir_type);
  2020. +   bmp = &(bm_bitmaps[bitmapnum].bm);
  2021.  
  2022. -   if (test != NULL) {
  2023. -       if (img_cfp != NULL)
  2024. -           *img_cfp = test;
  2025. +   if (w) *w = bmp->w;
  2026. +   if (h) *h = bmp->h;
  2027. +   if (flags) *flags = bmp->flags;
  2028.  
  2029. -       return rval;
  2030. +   if ((bm_bitmaps[bitmapnum].type == BM_TYPE_ANI) || (bm_bitmaps[bitmapnum].type == BM_TYPE_EFF)) {
  2031. +       if (nframes) {
  2032. +           *nframes = bm_bitmaps[bitmapnum].info.ani.num_frames;
  2033. +       }
  2034. +       if (fps) {
  2035. +           *fps = bm_bitmaps[bitmapnum].info.ani.fps;
  2036. +       }
  2037. +
  2038. +       return bm_bitmaps[bm_bitmaps[bitmapnum].info.ani.first_frame].handle;
  2039.     }
  2040. +   else {
  2041. +       if (nframes) {
  2042. +           *nframes = 1;
  2043. +       }
  2044. +       if (fps) {
  2045. +           *fps = 0;
  2046. +       }
  2047.  
  2048. -   // umm, that's not good...
  2049. -   return -1;
  2050. +       return handle;
  2051. +   }
  2052.  }
  2053.  
  2054. -bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug) {
  2055. -   bitmap          *bmp;
  2056. -   bitmap_entry    *be;
  2057. -
  2058. +/**
  2059. +* Gets the image type
  2060. +*/
  2061. +ubyte bm_get_type(int handle)
  2062. +{
  2063.     if (!bm_inited) bm_init();
  2064.  
  2065.     int bitmapnum = handle % MAX_BITMAPS;
  2066. +   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid bitmap handle %d passed to bm_get_type().\nThis might be due to an invalid animation somewhere else.\n", handle);        // INVALID BITMAP HANDLE!
  2067.  
  2068. -   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid handle %d passed to bm_lock. This might be due to an animation elsewhere in the code being too short.\n", handle);       // INVALID BITMAP HANDLE
  2069. +   return bm_bitmaps[bitmapnum].type;
  2070. +}
  2071.  
  2072. -   // to fix a couple of OGL bpp passes, force 8bit on AABITMAP - taylor
  2073. -   if (flags & BMP_AABITMAP)
  2074. -       bpp = 8;
  2075. +static void bm_convert_format(bitmap *bmp, ubyte flags)
  2076. +{
  2077. +   int idx;
  2078. +
  2079. +   // no transparency for 24 bpp images
  2080. +   if (!(flags & BMP_AABITMAP) && (bmp->bpp == 24))
  2081. +       return;
  2082.  
  2083. -   // if we're on a standalone server, aways for it to lock to 8 bits
  2084.     if (Is_standalone) {
  2085. -       bpp = 8;
  2086. -       flags = 0;
  2087. +       Assert(bmp->bpp == 8);
  2088. +       return;
  2089.     }
  2090. -   // otherwise do it as normal
  2091.     else {
  2092. -       if (flags & BMP_AABITMAP) {
  2093. -           Assert(bpp == 8);
  2094. -       } else if ((flags & BMP_TEX_NONCOMP) && (!(flags & BMP_TEX_COMP))) {
  2095. -           Assert(bpp >= 16);  // cheating but bpp passed isn't what we normally end up with
  2096. -       } else if ((flags & BMP_TEX_DXT1) || (flags & BMP_TEX_DXT3) || (flags & BMP_TEX_DXT5)) {
  2097. -           Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
  2098. -       } else if (flags & BMP_TEX_CUBEMAP) {
  2099. -           Assert((bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DDS) ||
  2100. -               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT1) ||
  2101. -               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT3) ||
  2102. -               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT5));
  2103. -           Assert(bpp >= 16);
  2104. -       } else {
  2105. -           Assert(0);      //?
  2106. +       if (flags & BMP_AABITMAP)
  2107. +           Assert(bmp->bpp == 8);
  2108. +       else
  2109. +           Assert((bmp->bpp == 16) || (bmp->bpp == 32));
  2110. +   }
  2111. +
  2112. +   // maybe swizzle to be an xparent texture
  2113. +   if (!(bmp->flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_XPARENT)) {
  2114. +       for (idx = 0; idx<bmp->w*bmp->h; idx++) {
  2115. +           // if the pixel is transparent
  2116. +           if (((ushort*)bmp->data)[idx] == Gr_t_green.mask) {
  2117. +               ((ushort*)bmp->data)[idx] = 0;
  2118. +           }
  2119.         }
  2120. +
  2121. +       bmp->flags |= BMP_TEX_XPARENT;
  2122.     }
  2123. +}
  2124.  
  2125. -   be = &bm_bitmaps[bitmapnum];
  2126. -   bmp = &be->bm;
  2127. +// basically, map the bitmap into the current palette. used to be done for all pcx's, now just for
  2128. +// Fred, since its the only thing that uses the software tmapper
  2129. +void bm_swizzle_8bit_for_fred(bitmap_entry *be, bitmap *bmp, ubyte *data, ubyte *palette)
  2130. +{
  2131. +   /* 2004/10/17 - taylor - no longer needed since FRED is OGL now*/
  2132. +}
  2133.  
  2134. -   // If you hit this assert, chances are that someone freed the
  2135. -   // wrong bitmap and now someone is trying to use that bitmap.
  2136. -   // See John.
  2137. -   Assert(be->type != BM_TYPE_NONE);
  2138. +void bm_lock_pcx(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2139. +{
  2140. +   ubyte *data;
  2141. +   int pcx_error;
  2142. +   char filename[MAX_FILENAME_LEN];
  2143.  
  2144. -   // Increment ref count for bitmap since lock was made on it.
  2145. -   Assert(be->ref_count >= 0);
  2146. -   be->ref_count++;                    // Lock it before we page in data; this prevents a callback from freeing this
  2147. -   // as it gets read in
  2148. +   // Unload any existing data
  2149. +   bm_free_data(bitmapnum);
  2150. +
  2151. +   be->mem_taken = (bmp->w * bmp->h * (bpp >> 3));
  2152. +   data = (ubyte *)bm_malloc(bitmapnum, be->mem_taken);
  2153. +   bmp->bpp = bpp;
  2154. +   bmp->data = (ptr_u)data;
  2155. +   bmp->palette = (bpp == 8) ? gr_palette : NULL;
  2156. +   memset(data, 0, be->mem_taken);
  2157.  
  2158. -   // Mark this bitmap as used this frame
  2159. +   Assert(&be->bm == bmp);
  2160.  #ifdef BMPMAN_NDEBUG
  2161. -   if (be->used_this_frame < 255) {
  2162. -       be->used_this_frame++;
  2163. -   }
  2164. +   Assert(be->data_size > 0);
  2165.  #endif
  2166.  
  2167. -   // read the file data
  2168. -   if (gr_bm_lock(be->filename, handle, bitmapnum, bpp, flags, nodebug) == -1) {
  2169. -       // oops, this isn't good - reset and return NULL
  2170. -       bm_unlock( handle );
  2171. -       bm_unload( handle );
  2172. -
  2173. -       return NULL;
  2174. -   }
  2175. +   // some sanity checks on flags
  2176. +   Assert(!((flags & BMP_AABITMAP) && (flags & BMP_TEX_ANY)));                     // no aabitmap textures
  2177.  
  2178. -   MONITOR_INC(NumBitmapPage, 1);
  2179. -   MONITOR_INC(SizeBitmapPage, bmp->w*bmp->h);
  2180. +                                                                                   // make sure we are using the correct filename in the case of an EFF.
  2181. +                                                                                   // this will populate filename[] whether it's EFF or not
  2182. +   EFF_FILENAME_CHECK;
  2183.  
  2184. -   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  2185. -       int i, first = bm_bitmaps[bitmapnum].info.ani.first_frame;
  2186. +   pcx_error = pcx_read_bitmap(filename, data, NULL, (bpp >> 3), (flags & BMP_AABITMAP), 0, be->dir_type);
  2187.  
  2188. -       for (i = 0; i< bm_bitmaps[first].info.ani.num_frames; i++) {
  2189. -           // Mark all the bitmaps in this bitmap or animation as recently used
  2190. -           bm_bitmaps[first + i].last_used = timer_get_milliseconds();
  2191. +   if (pcx_error != PCX_ERROR_NONE) {
  2192. +       mprintf(("Couldn't load PCX!!! (%s)\n", filename));
  2193. +       return;
  2194. +   }
  2195.  
  2196.  #ifdef BMPMAN_NDEBUG
  2197. -           // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
  2198. -           bm_bitmaps[first + i].used_count++;
  2199. -#endif
  2200. -
  2201. -           bm_bitmaps[first + i].used_flags = flags;
  2202. -       }
  2203. -   } else {
  2204. -       // Mark all the bitmaps in this bitmap or animation as recently used
  2205. -       be->last_used = timer_get_milliseconds();
  2206. +   Assert(be->data_size > 0);
  2207. +#endif    
  2208.  
  2209. -#ifdef BMPMAN_NDEBUG
  2210. -       // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
  2211. -       be->used_count++;
  2212. -#endif
  2213. -       be->used_flags = flags;
  2214. -   }
  2215. +   bmp->flags = 0;
  2216.  
  2217. -   return bmp;
  2218. +   bm_convert_format(bmp, flags);
  2219.  }
  2220.  
  2221. -void bm_lock_ani(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2222. +void bm_lock_ani(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2223. +{
  2224.     anim                *the_anim;
  2225.     anim_instance   *the_anim_instance;
  2226.     bitmap          *bm;
  2227. @@ -1573,7 +1315,7 @@ void bm_lock_ani(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2228.  
  2229.     bm = &bm_bitmaps[first_frame].bm;
  2230.     size = bm->w * bm->h * (bpp >> 3);
  2231. -   be->mem_taken = (size_t)size;
  2232. +   be->mem_taken = size;
  2233.  
  2234.     Assert(size > 0);
  2235.  
  2236. @@ -1646,7 +1388,8 @@ void bm_lock_ani(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2237.                     v += dv;
  2238.                 }
  2239.             }
  2240. -       } else {
  2241. +       }
  2242. +       else {
  2243.             // 1-to-1 mapping
  2244.             memcpy(dptr, sptr, size);
  2245.         }
  2246. @@ -1663,7 +1406,114 @@ void bm_lock_ani(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2247.     anim_free(the_anim);
  2248.  }
  2249.  
  2250. -void bm_lock_dds(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2251. +
  2252. +void bm_lock_user(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2253. +{
  2254. +   // Unload any existing data
  2255. +   bm_free_data(bitmapnum);
  2256. +
  2257. +   if ((bpp != be->info.user.bpp) && !(flags & BMP_AABITMAP))
  2258. +       bpp = be->info.user.bpp;
  2259. +
  2260. +   switch (bpp) {
  2261. +   case 32:    // user 32-bit bitmap
  2262. +       bmp->bpp = bpp;
  2263. +       bmp->flags = be->info.user.flags;
  2264. +       bmp->data = (ptr_u)be->info.user.data;
  2265. +       break;
  2266. +
  2267. +   case 24:    // user 24-bit bitmap
  2268. +       bmp->bpp = bpp;
  2269. +       bmp->flags = be->info.user.flags;
  2270. +       bmp->data = (ptr_u)be->info.user.data;
  2271. +       break;
  2272. +
  2273. +   case 16:            // user 16 bit bitmap
  2274. +       bmp->bpp = bpp;
  2275. +       bmp->flags = be->info.user.flags;
  2276. +       bmp->data = (ptr_u)be->info.user.data;
  2277. +       break;
  2278. +
  2279. +   case 8:         // Going from 8 bpp to something (probably only for aabitmaps)
  2280. +       Assert(flags & BMP_AABITMAP);
  2281. +       bmp->bpp = bpp;
  2282. +       bmp->flags = be->info.user.flags;
  2283. +       bmp->data = (ptr_u)be->info.user.data;
  2284. +       break;
  2285. +
  2286. +   default:
  2287. +       Error(LOCATION, "Unhandled user bitmap conversion from %d to %d bpp", be->info.user.bpp, bmp->bpp);
  2288. +       break;
  2289. +   }
  2290. +
  2291. +   bm_convert_format(bmp, flags);
  2292. +}
  2293. +
  2294. +void bm_lock_tga(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2295. +{
  2296. +   ubyte *data = NULL;
  2297. +   int d_size, byte_size;
  2298. +   char filename[MAX_FILENAME_LEN];
  2299. +
  2300. +   // Unload any existing data
  2301. +   bm_free_data(bitmapnum);
  2302. +
  2303. +   if (Is_standalone) {
  2304. +       Assert(bpp == 8);
  2305. +   }
  2306. +   else
  2307. +   {
  2308. +       Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
  2309. +   }
  2310. +
  2311. +   // allocate bitmap data
  2312. +   byte_size = (bpp >> 3);
  2313. +
  2314. +   Assert(byte_size);
  2315. +   Assert(be->mem_taken > 0);
  2316. +
  2317. +   data = (ubyte*)bm_malloc(bitmapnum, be->mem_taken);
  2318. +
  2319. +   if (data) {
  2320. +       memset(data, 0, be->mem_taken);
  2321. +       d_size = byte_size;
  2322. +   }
  2323. +   else {
  2324. +       return;
  2325. +   }
  2326. +
  2327. +   bmp->bpp = bpp;
  2328. +   bmp->data = (ptr_u)data;
  2329. +   bmp->palette = NULL;
  2330. +
  2331. +   Assert(&be->bm == bmp);
  2332. +#ifdef BMPMAN_NDEBUG
  2333. +   Assert(be->data_size > 0);
  2334. +#endif
  2335. +
  2336. +   int tga_error;
  2337. +
  2338. +   // make sure we are using the correct filename in the case of an EFF.
  2339. +   // this will populate filename[] whether it's EFF or not
  2340. +   EFF_FILENAME_CHECK;
  2341. +
  2342. +   tga_error = targa_read_bitmap(filename, data, NULL, d_size, be->dir_type);
  2343. +
  2344. +   if (tga_error != TARGA_ERROR_NONE) {
  2345. +       bm_free_data(bitmapnum);
  2346. +       return;
  2347. +   }
  2348. +
  2349. +   bmp->flags = 0;
  2350. +
  2351. +   bm_convert_format(bmp, flags);
  2352. +}
  2353. +
  2354. +/**
  2355. +* Lock a DDS file
  2356. +*/
  2357. +void bm_lock_dds(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2358. +{
  2359.     ubyte *data = NULL;
  2360.     int error;
  2361.     ubyte dds_bpp = 0;
  2362. @@ -1691,19 +1541,20 @@ void bm_lock_dds(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2363.  #if BYTE_ORDER == BIG_ENDIAN
  2364.     // same as with TGA, we need to byte swap 16 & 32-bit, uncompressed, DDS images
  2365.     if ((be->comp_type == BM_TYPE_DDS) || (be->comp_type == BM_TYPE_CUBEMAP_DDS)) {
  2366. -       size_t i = 0;
  2367. +       unsigned int i = 0;
  2368.  
  2369.         if (dds_bpp == 32) {
  2370.             unsigned int *swap_tmp;
  2371.  
  2372. -           for (i = 0; i < be->mem_taken; i += 4) {
  2373. +           for (i = 0; i < (unsigned int)be->mem_taken; i += 4) {
  2374.                 swap_tmp = (unsigned int *)(data + i);
  2375.                 *swap_tmp = INTEL_INT(*swap_tmp);
  2376.             }
  2377. -       } else if (dds_bpp == 16) {
  2378. +       }
  2379. +       else if (dds_bpp == 16) {
  2380.             unsigned short *swap_tmp;
  2381.  
  2382. -           for (i = 0; i < be->mem_taken; i += 2) {
  2383. +           for (i = 0; i < (unsigned int)be->mem_taken; i += 2) {
  2384.                 swap_tmp = (unsigned short *)(data + i);
  2385.                 *swap_tmp = INTEL_SHORT(*swap_tmp);
  2386.             }
  2387. @@ -1725,92 +1576,11 @@ void bm_lock_dds(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2388.  #endif
  2389.  }
  2390.  
  2391. -void bm_lock_jpg(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2392. -   ubyte *data = NULL;
  2393. -   int d_size = 0;
  2394. -   int jpg_error = JPEG_ERROR_INVALID;
  2395. -   char filename[MAX_FILENAME_LEN];
  2396. -
  2397. -   // Unload any existing data
  2398. -   bm_free_data(bitmapnum);
  2399. -
  2400. -   d_size = (bpp >> 3);
  2401. -
  2402. -   // allocate bitmap data
  2403. -   Assert(be->mem_taken > 0);
  2404. -   data = (ubyte*)bm_malloc(bitmapnum, be->mem_taken);
  2405. -
  2406. -   if (data == NULL)
  2407. -       return;
  2408. -
  2409. -   memset(data, 0, be->mem_taken);
  2410. -
  2411. -   bmp->bpp = bpp;
  2412. -   bmp->data = (ptr_u)data;
  2413. -   bmp->palette = NULL;
  2414. -
  2415. -   Assert(&be->bm == bmp);
  2416. -
  2417. -   // make sure we are using the correct filename in the case of an EFF.
  2418. -   // this will populate filename[] whether it's EFF or not
  2419. -   EFF_FILENAME_CHECK;
  2420. -
  2421. -   jpg_error = jpeg_read_bitmap(filename, data, NULL, d_size, be->dir_type);
  2422. -
  2423. -   if (jpg_error != JPEG_ERROR_NONE) {
  2424. -       bm_free_data(bitmapnum);
  2425. -       return;
  2426. -   }
  2427. -
  2428. -#ifdef BMPMAN_NDEBUG
  2429. -   Assert(be->data_size > 0);
  2430. -#endif
  2431. -}
  2432. -
  2433. -void bm_lock_pcx(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2434. -   ubyte *data;
  2435. -   int pcx_error;
  2436. -   char filename[MAX_FILENAME_LEN];
  2437. -
  2438. -   // Unload any existing data
  2439. -   bm_free_data(bitmapnum);
  2440. -
  2441. -   be->mem_taken = (bmp->w * bmp->h * (bpp >> 3));
  2442. -   data = (ubyte *)bm_malloc(bitmapnum, be->mem_taken);
  2443. -   bmp->bpp = bpp;
  2444. -   bmp->data = (ptr_u)data;
  2445. -   bmp->palette = (bpp == 8) ? gr_palette : NULL;
  2446. -   memset(data, 0, be->mem_taken);
  2447. -
  2448. -   Assert(&be->bm == bmp);
  2449. -#ifdef BMPMAN_NDEBUG
  2450. -   Assert(be->data_size > 0);
  2451. -#endif
  2452. -
  2453. -   // some sanity checks on flags
  2454. -   Assert(!((flags & BMP_AABITMAP) && (flags & BMP_TEX_ANY)));                     // no aabitmap textures
  2455. -
  2456. -   // make sure we are using the correct filename in the case of an EFF.
  2457. -   // this will populate filename[] whether it's EFF or not
  2458. -   EFF_FILENAME_CHECK;
  2459. -
  2460. -   pcx_error = pcx_read_bitmap(filename, data, NULL, (bpp >> 3), (flags & BMP_AABITMAP), 0, be->dir_type);
  2461. -
  2462. -   if (pcx_error != PCX_ERROR_NONE) {
  2463. -       mprintf(("Couldn't load PCX!!! (%s)\n", filename));
  2464. -       return;
  2465. -   }
  2466. -
  2467. -#ifdef BMPMAN_NDEBUG
  2468. -   Assert(be->data_size > 0);
  2469. -#endif
  2470. -
  2471. -   bmp->flags = 0;
  2472. -
  2473. -   bm_convert_format(bmp, flags);
  2474. -}
  2475. -
  2476. -void bm_lock_png(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2477. +/**
  2478. +* Lock a PNG file
  2479. +*/
  2480. +void bm_lock_png(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2481. +{
  2482.     ubyte *data = NULL;
  2483.     //assume 32 bit - libpng should expand everything
  2484.     int d_size;
  2485. @@ -1853,191 +1623,640 @@ void bm_lock_png(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte
  2486.  #endif
  2487.  }
  2488.  
  2489. -void bm_lock_tga(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2490. +/**
  2491. +* Lock a JPEG file
  2492. +*/
  2493. +void bm_lock_jpg(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags)
  2494. +{
  2495.     ubyte *data = NULL;
  2496. -   int d_size, byte_size;
  2497. +   int d_size = 0;
  2498. +   int jpg_error = JPEG_ERROR_INVALID;
  2499.     char filename[MAX_FILENAME_LEN];
  2500.  
  2501.     // Unload any existing data
  2502.     bm_free_data(bitmapnum);
  2503.  
  2504. -   if (Is_standalone) {
  2505. -       Assert(bpp == 8);
  2506. -   } else {
  2507. -       Assert((bpp == 16) || (bpp == 24) || (bpp == 32));
  2508. -   }
  2509. +   d_size = (bpp >> 3);
  2510.  
  2511.     // allocate bitmap data
  2512. -   byte_size = (bpp >> 3);
  2513. -
  2514. -   Assert(byte_size);
  2515.     Assert(be->mem_taken > 0);
  2516. -
  2517.     data = (ubyte*)bm_malloc(bitmapnum, be->mem_taken);
  2518.  
  2519. -   if (data) {
  2520. -       memset(data, 0, be->mem_taken);
  2521. -       d_size = byte_size;
  2522. -   } else {
  2523. +   if (data == NULL)
  2524.         return;
  2525. -   }
  2526. +
  2527. +   memset(data, 0, be->mem_taken);
  2528.  
  2529.     bmp->bpp = bpp;
  2530.     bmp->data = (ptr_u)data;
  2531.     bmp->palette = NULL;
  2532.  
  2533.     Assert(&be->bm == bmp);
  2534. -#ifdef BMPMAN_NDEBUG
  2535. -   Assert(be->data_size > 0);
  2536. -#endif
  2537. -
  2538. -   int tga_error;
  2539.  
  2540.     // make sure we are using the correct filename in the case of an EFF.
  2541.     // this will populate filename[] whether it's EFF or not
  2542.     EFF_FILENAME_CHECK;
  2543.  
  2544. -   tga_error = targa_read_bitmap(filename, data, NULL, d_size, be->dir_type);
  2545. +   jpg_error = jpeg_read_bitmap(filename, data, NULL, d_size, be->dir_type);
  2546.  
  2547. -   if (tga_error != TARGA_ERROR_NONE) {
  2548. +   if (jpg_error != JPEG_ERROR_NONE) {
  2549.         bm_free_data(bitmapnum);
  2550.         return;
  2551.     }
  2552.  
  2553. -   bmp->flags = 0;
  2554. -
  2555. -   bm_convert_format(bmp, flags);
  2556. +#ifdef BMPMAN_NDEBUG
  2557. +   Assert(be->data_size > 0);
  2558. +#endif
  2559.  }
  2560.  
  2561. -void bm_lock_user(int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags) {
  2562. -   // Unload any existing data
  2563. -   bm_free_data(bitmapnum);
  2564. +MONITOR(NumBitmapPage)
  2565. +MONITOR(SizeBitmapPage)
  2566.  
  2567. -   if ((bpp != be->info.user.bpp) && !(flags & BMP_AABITMAP))
  2568. -       bpp = be->info.user.bpp;
  2569. +/**
  2570. +* This locks down a bitmap and returns a pointer to a bitmap that can be accessed until you call bm_unlock.
  2571. +*
  2572. +* Only lock a bitmap when you need it! This will convert it into the appropriate format also.
  2573. +*/
  2574. +bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug)
  2575. +{
  2576. +   bitmap          *bmp;
  2577. +   bitmap_entry    *be;
  2578.  
  2579. -   switch (bpp) {
  2580. -   case 32:    // user 32-bit bitmap
  2581. -       bmp->bpp = bpp;
  2582. -       bmp->flags = be->info.user.flags;
  2583. -       bmp->data = (ptr_u)be->info.user.data;
  2584. -       break;
  2585. +   if (!bm_inited) bm_init();
  2586.  
  2587. -   case 24:    // user 24-bit bitmap
  2588. -       bmp->bpp = bpp;
  2589. -       bmp->flags = be->info.user.flags;
  2590. -       bmp->data = (ptr_u)be->info.user.data;
  2591. -       break;
  2592. +   int bitmapnum = handle % MAX_BITMAPS;
  2593.  
  2594. -   case 16:            // user 16 bit bitmap
  2595. -       bmp->bpp = bpp;
  2596. -       bmp->flags = be->info.user.flags;
  2597. -       bmp->data = (ptr_u)be->info.user.data;
  2598. -       break;
  2599. +   Assertion(bm_bitmaps[bitmapnum].handle == handle, "Invalid handle %d passed to bm_lock. This might be due to an animation elsewhere in the code being too short.\n", handle);       // INVALID BITMAP HANDLE
  2600.  
  2601. -   case 8:         // Going from 8 bpp to something (probably only for aabitmaps)
  2602. -       Assert(flags & BMP_AABITMAP);
  2603. -       bmp->bpp = bpp;
  2604. -       bmp->flags = be->info.user.flags;
  2605. -       bmp->data = (ptr_u)be->info.user.data;
  2606. -       break;
  2607. +                                                                                                                                                                                       // to fix a couple of OGL bpp passes, force 8bit on AABITMAP - taylor
  2608. +   if (flags & BMP_AABITMAP)
  2609. +       bpp = 8;
  2610.  
  2611. -   default:
  2612. -       Error(LOCATION, "Unhandled user bitmap conversion from %d to %d bpp", be->info.user.bpp, bmp->bpp);
  2613. -       break;
  2614. +   // if we're on a standalone server, aways for it to lock to 8 bits
  2615. +   if (Is_standalone) {
  2616. +       bpp = 8;
  2617. +       flags = 0;
  2618. +   }
  2619. +   // otherwise do it as normal
  2620. +   else {
  2621. +       if (flags & BMP_AABITMAP) {
  2622. +           Assert(bpp == 8);
  2623. +       }
  2624. +       else if ((flags & BMP_TEX_NONCOMP) && (!(flags & BMP_TEX_COMP))) {
  2625. +           Assert(bpp >= 16);  // cheating but bpp passed isn't what we normally end up with
  2626. +       }
  2627. +       else if ((flags & BMP_TEX_DXT1) || (flags & BMP_TEX_DXT3) || (flags & BMP_TEX_DXT5)) {
  2628. +           Assert(bpp >= 16); // cheating but bpp passed isn't what we normally end up with
  2629. +       }
  2630. +       else if (flags & BMP_TEX_CUBEMAP) {
  2631. +           Assert((bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DDS) ||
  2632. +               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT1) ||
  2633. +               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT3) ||
  2634. +               (bm_bitmaps[bitmapnum].type == BM_TYPE_CUBEMAP_DXT5));
  2635. +           Assert(bpp >= 16);
  2636. +       }
  2637. +       else {
  2638. +           Assert(0);      //?
  2639. +       }
  2640.     }
  2641.  
  2642. -   bm_convert_format(bmp, flags);
  2643. -}
  2644. +   be = &bm_bitmaps[bitmapnum];
  2645. +   bmp = &be->bm;
  2646.  
  2647. -int bm_make_render_target(int width, int height, int flags) {
  2648. -   int i, n;
  2649. -   int mm_lvl = 0;
  2650. -   // final w and h may be different from passed width and height
  2651. -   int w = width, h = height;
  2652. -   ubyte bpp = 32;
  2653. -   int size = 0;
  2654. +   // If you hit this assert, chances are that someone freed the
  2655. +   // wrong bitmap and now someone is trying to use that bitmap.
  2656. +   // See John.
  2657. +   Assert(be->type != BM_TYPE_NONE);
  2658.  
  2659. -   if (!bm_inited)
  2660. -       bm_init();
  2661. +   // Increment ref count for bitmap since lock was made on it.
  2662. +   Assert(be->ref_count >= 0);
  2663. +   be->ref_count++;                    // Lock it before we page in data; this prevents a callback from freeing this
  2664. +                                       // as it gets read in
  2665.  
  2666. -   // Find an open slot (starting from the end)
  2667. -   for (n = -1, i = MAX_BITMAPS - 1; i >= 0; i--) {
  2668. -       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  2669. -           n = i;
  2670. -           break;
  2671. -       }
  2672. +                                       // Mark this bitmap as used this frame
  2673. +#ifdef BMPMAN_NDEBUG
  2674. +   if (be->used_this_frame < 255) {
  2675. +       be->used_this_frame++;
  2676.     }
  2677. +#endif
  2678.  
  2679. -   // Out of bitmap slots
  2680. -   if (n == -1)
  2681. -       return -1;
  2682. +   // read the file data
  2683. +   if (gr_bm_lock(be->filename, handle, bitmapnum, bpp, flags, nodebug) == -1) {
  2684. +       // oops, this isn't good - reset and return NULL
  2685. +       bm_unlock(bitmapnum);
  2686. +       bm_unload(bitmapnum);
  2687.  
  2688. -   if (!gr_bm_make_render_target(n, &w, &h, &bpp, &mm_lvl, flags))
  2689. -       return -1;
  2690. +       return NULL;
  2691. +   }
  2692.  
  2693. -   Assert(mm_lvl > 0);
  2694. +   MONITOR_INC(NumBitmapPage, 1);
  2695. +   MONITOR_INC(SizeBitmapPage, bmp->w*bmp->h);
  2696.  
  2697. -   if (flags & BMP_FLAG_RENDER_TARGET_STATIC) {
  2698. -       // data size
  2699. -       size = (w * h * (bpp >> 3));
  2700. +   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  2701. +       int i, first = bm_bitmaps[bitmapnum].info.ani.first_frame;
  2702.  
  2703. -       if (mm_lvl > 1) {
  2704. -           // include size of all mipmap levels (there should be a full chain)
  2705. -           size += (size / 3) - 1;
  2706. -       }
  2707. +       for (i = 0; i< bm_bitmaps[first].info.ani.num_frames; i++) {
  2708. +           // Mark all the bitmaps in this bitmap or animation as recently used
  2709. +           bm_bitmaps[first + i].last_used = timer_get_milliseconds();
  2710.  
  2711. -       // make sure to count all faces if a cubemap
  2712. -       if (flags & BMP_FLAG_CUBEMAP) {
  2713. -           size *= 6;
  2714. +#ifdef BMPMAN_NDEBUG
  2715. +           // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
  2716. +           bm_bitmaps[first + i].used_count++;
  2717. +#endif
  2718. +
  2719. +           bm_bitmaps[first + i].used_flags = flags;
  2720.         }
  2721.     }
  2722. +   else {
  2723. +       // Mark all the bitmaps in this bitmap or animation as recently used
  2724. +       be->last_used = timer_get_milliseconds();
  2725.  
  2726. -   // ensure fields are cleared out from previous bitmap
  2727. -   memset(&bm_bitmaps[n], 0, sizeof(bitmap_entry));
  2728. +#ifdef BMPMAN_NDEBUG
  2729. +       // Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
  2730. +       be->used_count++;
  2731. +#endif
  2732. +       be->used_flags = flags;
  2733. +   }
  2734.  
  2735. -   bm_bitmaps[n].type = (flags & BMP_FLAG_RENDER_TARGET_STATIC) ? BM_TYPE_RENDER_TARGET_STATIC : BM_TYPE_RENDER_TARGET_DYNAMIC;
  2736. -   bm_bitmaps[n].signature = Bm_next_signature++;
  2737. -   sprintf(bm_bitmaps[n].filename, "RT_%dx%d+%d", w, h, bpp);
  2738. -   bm_bitmaps[n].bm.w = (short)w;
  2739. -   bm_bitmaps[n].bm.h = (short)h;
  2740. -   bm_bitmaps[n].bm.rowsize = (short)w;
  2741. -   bm_bitmaps[n].bm.bpp = (ubyte)bpp;
  2742. -   bm_bitmaps[n].bm.true_bpp = (ubyte)bpp;
  2743. -   bm_bitmaps[n].bm.flags = (ubyte)flags;
  2744. -   bm_bitmaps[n].bm.data = 0;
  2745. -   bm_bitmaps[n].bm.palette = NULL;
  2746. -   bm_bitmaps[n].num_mipmaps = mm_lvl;
  2747. -   bm_bitmaps[n].mem_taken = (size_t)size;
  2748. -   bm_bitmaps[n].dir_type = CF_TYPE_ANY;
  2749. +   return bmp;
  2750. +}
  2751. +
  2752. +/**
  2753. +* Unlocks a bitmap
  2754. +*
  2755. +* Decrements the ref_count member of the bitmap_entry struct.  A bitmap can only be unloaded
  2756. +* when the ref_count is 0.
  2757. +*/
  2758. +void bm_unlock(int handle)
  2759. +{
  2760. +   bitmap_entry    *be;
  2761. +   bitmap          *bmp;
  2762. +
  2763. +   if (!bm_inited) bm_init();
  2764. +
  2765. +   int bitmapnum = handle % MAX_BITMAPS;
  2766. +
  2767. +#ifndef NDEBUG
  2768. +   if (bm_bitmaps[bitmapnum].handle != handle) {
  2769. +       mprintf(("bm_unlock - %s: bm_bitmaps[%d].handle = %d, handle = %d\n", bm_bitmaps[bitmapnum].filename, bitmapnum, bm_bitmaps[bitmapnum].handle, handle));
  2770. +   }
  2771. +#endif
  2772. +
  2773. +   Assert(bm_bitmaps[bitmapnum].handle == handle); // INVALID BITMAP HANDLE
  2774. +
  2775. +   Assert((bitmapnum >= 0) && (bitmapnum < MAX_BITMAPS));
  2776. +
  2777. +   be = &bm_bitmaps[bitmapnum];
  2778. +   bmp = &be->bm;
  2779. +
  2780. +   be->ref_count--;
  2781. +   Assert(be->ref_count >= 0);     // Trying to unlock data more times than lock was called!!!
  2782. +}
  2783. +
  2784. +const char *bm_get_filename(int handle)
  2785. +{
  2786. +   int n;
  2787. +
  2788. +   n = handle % MAX_BITMAPS;
  2789. +   Assert(bm_bitmaps[n].handle == handle);     // INVALID BITMAP HANDLE
  2790. +   return bm_bitmaps[n].filename;
  2791. +}
  2792. +
  2793. +void bm_get_palette(int handle, ubyte *pal, char *name)
  2794. +{
  2795. +   char *filename;
  2796. +   int w, h;
  2797. +
  2798. +   int n = handle % MAX_BITMAPS;
  2799. +   Assert(bm_bitmaps[n].handle == handle);     // INVALID BITMAP HANDLE
  2800. +
  2801. +   filename = bm_bitmaps[n].filename;
  2802. +
  2803. +   if (name) {
  2804. +       strcpy(name, filename);
  2805. +   }
  2806. +
  2807. +   int pcx_error = pcx_read_header(filename, NULL, &w, &h, NULL, pal);
  2808. +   if (pcx_error != PCX_ERROR_NONE) {
  2809. +       // Error(LOCATION, "Couldn't open '%s'\n", filename );
  2810. +   }
  2811. +}
  2812. +
  2813. +/**
  2814. +* Unloads the bitmap's data and entire slot, so bitmap 'handle' won't be valid anymore
  2815. +* NOTE: this releases the slot of EVERY frame in an ANI so don't pass any frame but the first
  2816. +*
  2817. +* @param handle                index into ::bm_bitmaps ( index returned from bm_load() or bm_create() )
  2818. +* @param clear_render_targets  Whether to release a render target
  2819. +*
  2820. +* @return  1 on successful release, 0 otherwise
  2821. +*/
  2822. +int bm_release(int handle, int clear_render_targets)
  2823. +{
  2824. +   Assert(handle >= 0);
  2825. +
  2826. +   bitmap_entry *be;
  2827. +
  2828. +   int n = handle % MAX_BITMAPS;
  2829. +
  2830. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  2831. +   be = &bm_bitmaps[n];
  2832. +
  2833. +   if (be->type == BM_TYPE_NONE) {
  2834. +       return 0;   // Already been released?
  2835. +   }
  2836. +
  2837. +   Assertion(be->handle == handle, "Invalid bitmap handle number %d (expected %d) for %s passed to bm_release()\n", be->handle, handle, be->filename);
  2838. +
  2839. +   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  2840. +       nprintf(("BmpMan", "Tried to release a render target!\n"));
  2841. +       return 0;
  2842. +   }
  2843. +
  2844. +   // If it is locked, cannot free it.
  2845. +   if (be->ref_count != 0) {
  2846. +       nprintf(("BmpMan", "Tried to release %s that has a lock count of %d.. not releasing\n", be->filename, be->ref_count));
  2847. +       return 0;
  2848. +   }
  2849. +
  2850. +   // kind of like ref_count except it gets around the lock/unlock usage problem
  2851. +   // this gets set for each bm_load() call so we can make sure and not unload it
  2852. +   // from memory, even if we *can*, until it's really not needed anymore
  2853. +   if (be->load_count > 0)
  2854. +       be->load_count--;
  2855. +
  2856. +   if (be->load_count != 0) {
  2857. +       nprintf(("BmpMan", "Tried to release %s that has a load count of %d.. not releasing\n", be->filename, be->load_count + 1));
  2858. +       return 0;
  2859. +   }
  2860. +
  2861. +   if (be->type != BM_TYPE_USER) {
  2862. +       nprintf(("BmpMan", "Releasing bitmap %s in slot %i with handle %i\n", be->filename, n, handle));
  2863. +   }
  2864. +
  2865. +   // be sure that all frames of an ani are unloaded - taylor
  2866. +   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  2867. +       int i, first = be->info.ani.first_frame, total = bm_bitmaps[first].info.ani.num_frames;
  2868. +
  2869. +       for (i = 0; i < total; i++) {
  2870. +           bm_free_data(first + i, true);      // clears flags, bbp, data, etc
  2871. +
  2872. +           memset(&bm_bitmaps[first + i], 0, sizeof(bitmap_entry));
  2873. +
  2874. +           bm_bitmaps[first + i].type = BM_TYPE_NONE;
  2875. +           bm_bitmaps[first + i].comp_type = BM_TYPE_NONE;
  2876. +           bm_bitmaps[first + i].dir_type = CF_TYPE_ANY;
  2877. +           // Fill in bogus structures!
  2878. +
  2879. +           // For debugging:
  2880. +           strcpy_s(bm_bitmaps[first + i].filename, "IVE_BEEN_RELEASED!");
  2881. +           bm_bitmaps[first + i].signature = 0xDEADBEEF;                                   // a unique signature identifying the data
  2882. +           bm_bitmaps[first + i].palette_checksum = 0xDEADBEEF;                            // checksum used to be sure bitmap is in current palette
  2883. +
  2884. +                                                                                           // bookeeping
  2885. +           bm_bitmaps[first + i].ref_count = -1;                                   // Number of locks on bitmap.  Can't unload unless ref_count is 0.
  2886. +
  2887. +                                                                                   // Stuff needed for animations
  2888. +           bm_bitmaps[first + i].info.ani.first_frame = -1;
  2889. +
  2890. +           bm_bitmaps[first + i].handle = -1;
  2891. +       }
  2892. +   }
  2893. +   else {
  2894. +       bm_free_data(n, true);      // clears flags, bbp, data, etc
  2895. +
  2896. +       memset(&bm_bitmaps[n], 0, sizeof(bitmap_entry));
  2897. +
  2898. +       bm_bitmaps[n].type = BM_TYPE_NONE;
  2899. +       bm_bitmaps[n].comp_type = BM_TYPE_NONE;
  2900. +       bm_bitmaps[n].dir_type = CF_TYPE_ANY;
  2901. +       // Fill in bogus structures!
  2902. +
  2903. +       // For debugging:
  2904. +       strcpy_s(bm_bitmaps[n].filename, "IVE_BEEN_RELEASED!");
  2905. +       bm_bitmaps[n].signature = 0xDEADBEEF;                                   // a unique signature identifying the data
  2906. +       bm_bitmaps[n].palette_checksum = 0xDEADBEEF;                            // checksum used to be sure bitmap is in current palette
  2907. +
  2908. +                                                                               // bookeeping
  2909. +       bm_bitmaps[n].ref_count = -1;                                   // Number of locks on bitmap.  Can't unload unless ref_count is 0.
  2910. +
  2911. +                                                                       // Stuff needed for animations
  2912. +       bm_bitmaps[n].info.ani.first_frame = -1;
  2913. +
  2914. +       bm_bitmaps[n].handle = -1;
  2915. +   }
  2916. +
  2917. +   return 1;
  2918. +}
  2919. +
  2920. +/**
  2921. +* Unloads the data, but not the bitmap info.
  2922. +*
  2923. +* @param handle                index into ::bm_bitmaps ( index returned from bm_load() or bm_create() )
  2924. +* @param clear_render_targets  Whether to release a render target
  2925. +* @param nodebug               Exclude certain debug messages
  2926. +*
  2927. +* @return  1 on successful release, 0 otherwise
  2928. +*/
  2929. +int bm_unload(int handle, int clear_render_targets, bool nodebug)
  2930. +{
  2931. +   bitmap_entry *be;
  2932. +   bitmap *bmp;
  2933. +
  2934. +   int n = handle % MAX_BITMAPS;
  2935. +
  2936. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  2937. +   be = &bm_bitmaps[n];
  2938. +   bmp = &be->bm;
  2939. +
  2940. +   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  2941. +       return -1;
  2942. +   }
  2943. +
  2944. +   if (be->type == BM_TYPE_NONE) {
  2945. +       return -1;      // Already been released
  2946. +   }
  2947. +
  2948. +   Assert(be->handle == handle);       // INVALID BITMAP HANDLE!
  2949. +
  2950. +                                       // If it is locked, cannot free it.
  2951. +   if (be->ref_count != 0 && !nodebug) {
  2952. +       nprintf(("BmpMan", "Tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
  2953. +       return 0;
  2954. +   }
  2955. +
  2956. +   // kind of like ref_count except it gets around the lock/unlock usage problem
  2957. +   // this gets set for each bm_load() call so we can make sure and not unload it
  2958. +   // from memory, even if we *can*, until it's really not needed anymore
  2959. +   if (!Bm_ignore_load_count) {
  2960. +       if (be->load_count > 0)
  2961. +           be->load_count--;
  2962. +
  2963. +       if (be->load_count != 0 && !nodebug) {
  2964. +           nprintf(("BmpMan", "Tried to unload %s that has a load count of %d.. not unloading\n", be->filename, be->load_count + 1));
  2965. +           return 0;
  2966. +       }
  2967. +   }
  2968. +
  2969. +   // be sure that all frames of an ani are unloaded - taylor
  2970. +   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  2971. +       int i, first = be->info.ani.first_frame;
  2972. +
  2973. +       // for the unload all case, don't try to unload every frame of every frame
  2974. +       // all additional frames automatically get unloaded with the first one
  2975. +       if ((n > be->info.ani.first_frame) && (bm_bitmaps[first].bm.data == 0))
  2976. +           return 1;
  2977. +
  2978. +       for (i = 0; i < bm_bitmaps[first].info.ani.num_frames; i++) {
  2979. +           if (!nodebug)
  2980. +               nprintf(("BmpMan", "Unloading %s frame %d.  %dx%dx%d\n", be->filename, i, bmp->w, bmp->h, bmp->bpp));
  2981. +           bm_free_data(first + i);        // clears flags, bbp, data, etc
  2982. +       }
  2983. +   }
  2984. +   else {
  2985. +       if (!nodebug)
  2986. +           nprintf(("BmpMan", "Unloading %s.  %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
  2987. +       bm_free_data(n);        // clears flags, bbp, data, etc
  2988. +   }
  2989. +
  2990. +   return 1;
  2991. +}
  2992. +
  2993. +/**
  2994. +* Just like bm_unload() except that it doesn't care about what load_count is
  2995. +* and will just plow through and release the data anyway
  2996. +*
  2997. +* NOTE: that bm_free_data_fast() is used here and NOT bm_free_data()!
  2998. +*/
  2999. +int bm_unload_fast(int handle, int clear_render_targets)
  3000. +{
  3001. +   bitmap_entry *be;
  3002. +   bitmap *bmp;
  3003. +
  3004. +   int n = handle % MAX_BITMAPS;
  3005. +
  3006. +   Assert((n >= 0) && (n < MAX_BITMAPS));
  3007. +   be = &bm_bitmaps[n];
  3008. +   bmp = &be->bm;
  3009. +
  3010. +   if (be->type == BM_TYPE_NONE) {
  3011. +       return -1;      // Already been released
  3012. +   }
  3013. +
  3014. +   if (be->type == BM_TYPE_USER) {
  3015. +       return -1;
  3016. +   }
  3017. +
  3018. +   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  3019. +       return -1;
  3020. +   }
  3021. +
  3022. +   // If it is locked, cannot free it.
  3023. +   if (be->ref_count != 0) {
  3024. +       nprintf(("BmpMan", "Tried to unload_fast %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
  3025. +       return 0;
  3026. +   }
  3027. +
  3028. +   Assert(be->handle == handle);       // INVALID BITMAP HANDLE!
  3029. +
  3030. +                                       // unlike bm_unload(), we handle each frame of an animation separately, for safer use in the graphics API
  3031. +   nprintf(("BmpMan", "Fast-unloading %s.  %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
  3032. +   bm_free_data_fast(n);       // clears flags, bbp, data, etc
  3033. +
  3034. +   return 1;
  3035. +}
  3036. +
  3037. +/**
  3038. +* Unload all used bitmaps
  3039. +*/
  3040. +void bm_unload_all()
  3041. +{
  3042. +   int i;
  3043. +
  3044. +   // since bm_unload_all() should only be called from game_shutdown() it should be
  3045. +   // safe to ignore load_count's and unload anyway
  3046. +   Bm_ignore_load_count = 1;
  3047. +
  3048. +   for (i = 0; i < MAX_BITMAPS; i++) {
  3049. +       if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  3050. +           bm_unload(bm_bitmaps[i].handle, 1);
  3051. +       }
  3052. +   }
  3053. +
  3054. +   Bm_ignore_load_count = 0;
  3055. +}
  3056. +
  3057. +
  3058. +DCF(bmpman, "Shows/changes bitmap caching parameters and usage")
  3059. +{
  3060. +   if (dc_optional_string_either("help", "--help")) {
  3061. +       dc_printf("Usage: BmpMan [arg]\nWhere arg can be any of the following:\n");
  3062. +       dc_printf("\tflush    Unloads all bitmaps.\n");
  3063. +       dc_printf("\tram [x]  Sets max mem usage to x MB. (Set to 0 to have no limit.)\n");
  3064. +       dc_printf("\t?        Displays status of Bitmap manager.\n");
  3065. +       return;
  3066. +   }
  3067. +
  3068. +   if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?")) {
  3069. +       dc_printf("Total RAM usage: %d bytes\n", bm_texture_ram);
  3070. +
  3071. +       if (Bm_max_ram > 1024 * 1024) {
  3072. +           dc_printf("\tMax RAM allowed: %.1f MB\n", i2fl(Bm_max_ram) / (1024.0f*1024.0f));
  3073. +       }
  3074. +       else if (Bm_max_ram > 1024) {
  3075. +           dc_printf("\tMax RAM allowed: %.1f KB\n", i2fl(Bm_max_ram) / (1024.0f));
  3076. +       }
  3077. +       else if (Bm_max_ram > 0) {
  3078. +           dc_printf("\tMax RAM allowed: %d bytes\n", Bm_max_ram);
  3079. +       }
  3080. +       else {
  3081. +           dc_printf("\tNo RAM limit\n");
  3082. +       }
  3083. +       return;
  3084. +   }
  3085. +
  3086. +
  3087. +   if (dc_optional_string("flush")) {
  3088. +       dc_printf("Total RAM usage before flush: %d bytes\n", bm_texture_ram);
  3089. +       int i;
  3090. +       for (i = 0; i < MAX_BITMAPS; i++) {
  3091. +           if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  3092. +               bm_free_data(i);
  3093. +           }
  3094. +       }
  3095. +       dc_printf("Total RAM after flush: %d bytes\n", bm_texture_ram);
  3096. +   }
  3097. +   else if (dc_optional_string("ram")) {
  3098. +       dc_stuff_int(&Bm_max_ram);
  3099. +
  3100. +       if (Bm_max_ram > 0) {
  3101. +           dc_printf("BmpMan limited to %i, MB's\n", Bm_max_ram);
  3102. +           Bm_max_ram *= 1024 * 1024;
  3103. +       }
  3104. +       else if (Bm_max_ram == 0) {
  3105. +           dc_printf("!!BmpMan memory is unlimited!!\n");
  3106. +       }
  3107. +       else {
  3108. +           dc_printf("Illegal value. Must be non-negative.");
  3109. +       }
  3110. +   }
  3111. +   else {
  3112. +       dc_printf("<BmpMan> No argument given\n");
  3113. +   }
  3114. +}
  3115. +
  3116. +/**
  3117. +* Marks a texture as being used for this level
  3118. +*/
  3119. +void bm_page_in_texture(int bitmapnum, int nframes)
  3120. +{
  3121. +   int i;
  3122. +   int n = bitmapnum % MAX_BITMAPS;
  3123. +
  3124. +   if (bitmapnum < 0)
  3125. +       return;
  3126. +
  3127. +   Assertion((bm_bitmaps[n].handle == bitmapnum), "bitmapnum = %i, n = %i, bm_bitmaps[n].handle = %i", bitmapnum, n, bm_bitmaps[n].handle);
  3128. +
  3129. +   if (nframes <= 0) {
  3130. +       if ((bm_bitmaps[n].type == BM_TYPE_ANI) || (bm_bitmaps[n].type == BM_TYPE_EFF))
  3131. +           nframes = bm_bitmaps[n].info.ani.num_frames;
  3132. +       else
  3133. +           nframes = 1;
  3134. +   }
  3135. +
  3136. +   for (i = 0; i < nframes;i++) {
  3137. +       bm_bitmaps[n + i].preloaded = 1;
  3138. +
  3139. +       bm_bitmaps[n + i].preload_count++;
  3140. +
  3141. +       bm_bitmaps[n + i].used_flags = BMP_TEX_OTHER;
  3142. +
  3143. +       //check if its compressed
  3144. +       switch (bm_bitmaps[n + i].comp_type)
  3145. +       {
  3146. +       case BM_TYPE_NONE:
  3147. +           continue;
  3148. +
  3149. +       case BM_TYPE_DXT1:
  3150. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT1;
  3151. +           continue;
  3152. +
  3153. +       case BM_TYPE_DXT3:
  3154. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT3;
  3155. +           continue;
  3156. +
  3157. +       case BM_TYPE_DXT5:
  3158. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT5;
  3159. +           continue;
  3160. +
  3161. +       case BM_TYPE_CUBEMAP_DXT1:
  3162. +       case BM_TYPE_CUBEMAP_DXT3:
  3163. +       case BM_TYPE_CUBEMAP_DXT5:
  3164. +           bm_bitmaps[n + i].used_flags = BMP_TEX_CUBEMAP;
  3165. +           continue;
  3166. +       }
  3167. +   }
  3168. +}
  3169. +
  3170. +/**
  3171. +* Marks a texture as being a transparent texture used for this level
  3172. +*
  3173. +* @param bitmapnum Index into ::bm_bitmaps ( index returned from bm_load() or bm_create() )
  3174. +* @param nframes   Animation number of frames
  3175. +*/
  3176. +void bm_page_in_xparent_texture(int bitmapnum, int nframes)
  3177. +{
  3178. +   int i;
  3179. +   int n = bitmapnum % MAX_BITMAPS;
  3180. +
  3181. +   if (n == -1)
  3182. +       return;
  3183. +
  3184. +   Assert(bm_bitmaps[n].handle == bitmapnum);
  3185. +
  3186. +   for (i = 0; i < nframes; i++) {
  3187. +       bm_bitmaps[n + i].preloaded = 3;
  3188.  
  3189. -   bm_bitmaps[n].palette_checksum = 0;
  3190. -   bm_bitmaps[n].handle = bm_get_next_handle() * MAX_BITMAPS + n;
  3191. -   bm_bitmaps[n].last_used = -1;
  3192. +       bm_bitmaps[n + i].preload_count++;
  3193.  
  3194. -   if (bm_bitmaps[n].mem_taken) {
  3195. -       bm_bitmaps[n].bm.data = (ptr_u)bm_malloc(n, bm_bitmaps[n].mem_taken);
  3196. -   }
  3197. +       bm_bitmaps[n + i].used_flags = BMP_TEX_XPARENT;
  3198.  
  3199. -   return bm_bitmaps[n].handle;
  3200. -}
  3201. +       //check if its compressed
  3202. +       switch (bm_bitmaps[n + i].comp_type)
  3203. +       {
  3204. +       case BM_TYPE_NONE:
  3205. +           continue;
  3206.  
  3207. -void *bm_malloc(int n, int size) {
  3208. -   Assert((n >= 0) && (n < MAX_BITMAPS));
  3209. +       case BM_TYPE_DXT1:
  3210. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT1;
  3211. +           continue;
  3212.  
  3213. -   if (size <= 0)
  3214. -       return NULL;
  3215. +       case BM_TYPE_DXT3:
  3216. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT3;
  3217. +           continue;
  3218.  
  3219. -#ifdef BMPMAN_NDEBUG
  3220. -   Assert(bm_bitmaps[n].data_size == 0);
  3221. -   bm_bitmaps[n].data_size += size;
  3222. -   bm_texture_ram += size;
  3223. -#endif
  3224. +       case BM_TYPE_DXT5:
  3225. +           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT5;
  3226. +           continue;
  3227.  
  3228. -   return vm_malloc(size);
  3229. +       case BM_TYPE_CUBEMAP_DXT1:
  3230. +       case BM_TYPE_CUBEMAP_DXT3:
  3231. +       case BM_TYPE_CUBEMAP_DXT5:
  3232. +           bm_bitmaps[n + i].used_flags = BMP_TEX_CUBEMAP;
  3233. +           continue;
  3234. +       }
  3235. +   }
  3236.  }
  3237.  
  3238. -void bm_page_in_aabitmap(int bitmapnum, int nframes) {
  3239. +/**
  3240. +* Marks an aabitmap as being used for this level
  3241. +*
  3242. +* @param bitmapnum Index into ::bm_bitmaps ( index returned from bm_load() or bm_create() )
  3243. +* @param nframes   Animation number of frames
  3244. +*/
  3245. +void bm_page_in_aabitmap(int bitmapnum, int nframes)
  3246. +{
  3247.     int i;
  3248.     int n = bitmapnum % MAX_BITMAPS;
  3249.  
  3250. @@ -2046,7 +2265,7 @@ void bm_page_in_aabitmap(int bitmapnum, int nframes) {
  3251.  
  3252.     Assert(bm_bitmaps[n].handle == bitmapnum);
  3253.  
  3254. -   for (i = 0; i<nframes; i++) {
  3255. +   for (i = 0; i<nframes;i++) {
  3256.         bm_bitmaps[n + i].preloaded = 2;
  3257.  
  3258.         bm_bitmaps[n + i].preload_count++;
  3259. @@ -2055,7 +2274,11 @@ void bm_page_in_aabitmap(int bitmapnum, int nframes) {
  3260.     }
  3261.  }
  3262.  
  3263. -void bm_page_in_start() {
  3264. +/**
  3265. +* Tell the bitmap manager to start keeping track of what bitmaps are used where.
  3266. +*/
  3267. +void bm_page_in_start()
  3268. +{
  3269.     int i;
  3270.  
  3271.     Bm_paging = 1;
  3272. @@ -2076,7 +2299,10 @@ void bm_page_in_start() {
  3273.     gr_bm_page_in_start();
  3274.  }
  3275.  
  3276. -void bm_page_in_stop() {
  3277. +extern void multi_ping_send_all();
  3278. +
  3279. +void bm_page_in_stop()
  3280. +{
  3281.     int i;
  3282.  
  3283.  #ifndef NDEBUG
  3284. @@ -2098,11 +2324,10 @@ void bm_page_in_stop() {
  3285.                         mprintf(("Out of VRAM.  Done preloading.\n"));
  3286.                         bm_preloading = 0;
  3287.                     }
  3288. -               } else {
  3289. +               }
  3290. +               else {
  3291.                     bm_lock(bm_bitmaps[i].handle, (bm_bitmaps[i].used_flags == BMP_AABITMAP) ? 8 : 16, bm_bitmaps[i].used_flags);
  3292. -                   if (bm_bitmaps[i].ref_count >= 1) {
  3293. -                       bm_unlock( bm_bitmaps[i].handle );
  3294. -                   }
  3295. +                   bm_unlock(bm_bitmaps[i].handle);
  3296.                 }
  3297.  
  3298.                 n++;
  3299. @@ -2122,7 +2347,8 @@ void bm_page_in_stop() {
  3300.                     game_busy();
  3301.  #endif
  3302.                 }
  3303. -           } else {
  3304. +           }
  3305. +           else {
  3306.                 bm_unload_fast(bm_bitmaps[i].handle);
  3307.             }
  3308.         }
  3309. @@ -2145,355 +2371,515 @@ void bm_page_in_stop() {
  3310.     Bm_paging = 0;
  3311.  }
  3312.  
  3313. -void bm_page_in_texture(int bitmapnum, int nframes) {
  3314. -   int i;
  3315. -   int n = bitmapnum % MAX_BITMAPS;
  3316. +/**
  3317. +* For unloading bitmaps while a mission is going
  3318. +*/
  3319. +int bm_page_out(int bitmap_id)
  3320. +{
  3321. +   int n = bitmap_id % MAX_BITMAPS;
  3322.  
  3323. -   if (bitmapnum < 0)
  3324. +   Assert(n >= 0 && n < MAX_BITMAPS);
  3325. +
  3326. +   // in case it's already been released
  3327. +   if (bm_bitmaps[n].type == BM_TYPE_NONE)
  3328. +       return 0;
  3329. +
  3330. +   Assert(bm_bitmaps[n].handle == bitmap_id);  // INVALID BITMAP HANDLE
  3331. +
  3332. +                                               // it's possible to hit < 0 here when model_page_out_textures() is called from
  3333. +                                               // anywhere other than in a mission
  3334. +   if (bm_bitmaps[n].preload_count > 0) {
  3335. +       nprintf(("BmpMan", "PAGE-OUT: %s - preload_count remaining: %d\n", bm_bitmaps[n].filename, bm_bitmaps[n].preload_count));
  3336. +
  3337. +       // lets decrease it for next time around
  3338. +       bm_bitmaps[n].preload_count--;
  3339. +
  3340. +       return 0;
  3341. +   }
  3342. +
  3343. +   return (bm_unload(bitmap_id) == 1);
  3344. +}
  3345. +
  3346. +int bm_get_cache_slot(int bitmap_id, int separate_ani_frames)
  3347. +{
  3348. +   int n = bitmap_id % MAX_BITMAPS;
  3349. +
  3350. +   Assert(n >= 0);
  3351. +   Assert(bm_bitmaps[n].handle == bitmap_id);      // INVALID BITMAP HANDLE
  3352. +
  3353. +   bitmap_entry    *be = &bm_bitmaps[n];
  3354. +
  3355. +   if ((!separate_ani_frames) && ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF))) {
  3356. +       return be->info.ani.first_frame;
  3357. +   }
  3358. +
  3359. +   return n;
  3360. +
  3361. +}
  3362. +
  3363. +void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
  3364. +void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
  3365. +
  3366. +void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
  3367. +{
  3368. +   if (*av == 0) {
  3369. +       *((unsigned short*)pixel) = (unsigned short)Gr_current_green->mask;
  3370.         return;
  3371. +   }
  3372.  
  3373. -   Assertion((bm_bitmaps[n].handle == bitmapnum), "bitmapnum = %i, n = %i, bm_bitmaps[n].handle = %i", bitmapnum, n, bm_bitmaps[n].handle);
  3374. +   *((unsigned short*)pixel) = (unsigned short)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  3375. +   *((unsigned short*)pixel) |= (unsigned short)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  3376. +   *((unsigned short*)pixel) |= (unsigned short)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  3377. +}
  3378.  
  3379. -   if (nframes <= 0) {
  3380. -       if ((bm_bitmaps[n].type == BM_TYPE_ANI) || (bm_bitmaps[n].type == BM_TYPE_EFF))
  3381. -           nframes = bm_bitmaps[n].info.ani.num_frames;
  3382. -       else
  3383. -           nframes = 1;
  3384. +void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
  3385. +{
  3386. +   if (*av == 0) {
  3387. +       *((unsigned int*)pixel) = (unsigned int)Gr_current_green->mask;
  3388. +       return;
  3389.     }
  3390.  
  3391. -   for (i = 0; i < nframes; i++) {
  3392. -       bm_bitmaps[n + i].preloaded = 1;
  3393. +   *((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  3394. +   *((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  3395. +   *((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  3396. +}
  3397.  
  3398. -       bm_bitmaps[n + i].preload_count++;
  3399. +void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
  3400. +{
  3401. +   if (*av == 0) {
  3402. +       *((unsigned short*)pixel) = 0;
  3403. +       return;
  3404. +   }
  3405.  
  3406. -       bm_bitmaps[n + i].used_flags = BMP_TEX_OTHER;
  3407. +   *((unsigned short*)pixel) = (unsigned short)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  3408. +   *((unsigned short*)pixel) |= (unsigned short)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  3409. +   *((unsigned short*)pixel) |= (unsigned short)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  3410. +   *((unsigned short*)pixel) |= (unsigned short)(Gr_current_alpha->mask);
  3411. +}
  3412.  
  3413. -       //check if its compressed
  3414. -       switch (bm_bitmaps[n + i].comp_type) {
  3415. -       case BM_TYPE_NONE:
  3416. -           continue;
  3417. +void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av)
  3418. +{
  3419. +   if (*av == 0) {
  3420. +       *((unsigned int*)pixel) = 0;
  3421. +       return;
  3422. +   }
  3423.  
  3424. -       case BM_TYPE_DXT1:
  3425. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT1;
  3426. -           continue;
  3427. +   *((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  3428. +   *((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  3429. +   *((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  3430. +   *((unsigned int*)pixel) |= (unsigned int)(Gr_current_alpha->mask);
  3431. +}
  3432.  
  3433. -       case BM_TYPE_DXT3:
  3434. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT3;
  3435. -           continue;
  3436. +/**
  3437. +* For selecting pixel formats
  3438. +*/
  3439. +void BM_SELECT_SCREEN_FORMAT()
  3440. +{
  3441. +   Gr_current_red = &Gr_red;
  3442. +   Gr_current_green = &Gr_green;
  3443. +   Gr_current_blue = &Gr_blue;
  3444. +   Gr_current_alpha = &Gr_alpha;
  3445.  
  3446. -       case BM_TYPE_DXT5:
  3447. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT5;
  3448. -           continue;
  3449. +   // setup pointers
  3450. +   bm_set_components_32 = bm_set_components_argb_32_screen;
  3451. +   // should always assume that 16-bit is the default request
  3452. +   bm_set_components = bm_set_components_argb_16_screen;
  3453. +}
  3454.  
  3455. -       case BM_TYPE_CUBEMAP_DXT1:
  3456. -       case BM_TYPE_CUBEMAP_DXT3:
  3457. -       case BM_TYPE_CUBEMAP_DXT5:
  3458. -           bm_bitmaps[n + i].used_flags = BMP_TEX_CUBEMAP;
  3459. -           continue;
  3460. +void BM_SELECT_TEX_FORMAT()
  3461. +{
  3462. +   Gr_current_red = &Gr_t_red;
  3463. +   Gr_current_green = &Gr_t_green;
  3464. +   Gr_current_blue = &Gr_t_blue;
  3465. +   Gr_current_alpha = &Gr_t_alpha;
  3466.  
  3467. -       default:
  3468. -           continue;
  3469. +   // setup pointers
  3470. +   bm_set_components_32 = bm_set_components_argb_32_tex;
  3471. +   // should always assume that 16-bit is the default request
  3472. +   bm_set_components = bm_set_components_argb_16_tex;
  3473. +}
  3474. +
  3475. +void BM_SELECT_ALPHA_TEX_FORMAT()
  3476. +{
  3477. +   Gr_current_red = &Gr_ta_red;
  3478. +   Gr_current_green = &Gr_ta_green;
  3479. +   Gr_current_blue = &Gr_ta_blue;
  3480. +   Gr_current_alpha = &Gr_ta_alpha;
  3481. +
  3482. +   // setup pointers
  3483. +   bm_set_components_32 = bm_set_components_argb_32_tex;
  3484. +   // should always assume that 16-bit is the default request
  3485. +   bm_set_components = bm_set_components_argb_16_tex;
  3486. +}
  3487. +
  3488. +/**
  3489. +* Get the rgba components of a pixel, any of the parameters can be NULL
  3490. +*/
  3491. +void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a)
  3492. +{
  3493. +   int bit_32 = 0;
  3494. +
  3495. +   if ((gr_screen.bits_per_pixel == 32) && (Gr_current_red == &Gr_red)) {
  3496. +       bit_32 = 1;
  3497. +   }
  3498. +
  3499. +   if (r != NULL) {
  3500. +       if (bit_32) {
  3501. +           *r = ubyte(((*((unsigned int*)pixel) & Gr_current_red->mask) >> Gr_current_red->shift)*Gr_current_red->scale);
  3502. +       }
  3503. +       else {
  3504. +           *r = ubyte(((((unsigned short*)pixel)[0] & Gr_current_red->mask) >> Gr_current_red->shift)*Gr_current_red->scale);
  3505. +       }
  3506. +   }
  3507. +
  3508. +   if (g != NULL) {
  3509. +       if (bit_32) {
  3510. +           *g = ubyte(((*((unsigned int*)pixel) & Gr_current_green->mask) >> Gr_current_green->shift)*Gr_current_green->scale);
  3511. +       }
  3512. +       else {
  3513. +           *g = ubyte(((((unsigned short*)pixel)[0] & Gr_current_green->mask) >> Gr_current_green->shift)*Gr_current_green->scale);
  3514. +       }
  3515. +   }
  3516. +
  3517. +   if (b != NULL) {
  3518. +       if (bit_32) {
  3519. +           *b = ubyte(((*((unsigned int*)pixel) & Gr_current_blue->mask) >> Gr_current_blue->shift)*Gr_current_blue->scale);
  3520. +       }
  3521. +       else {
  3522. +           *b = ubyte(((((unsigned short*)pixel)[0] & Gr_current_blue->mask) >> Gr_current_blue->shift)*Gr_current_blue->scale);
  3523. +       }
  3524. +   }
  3525. +
  3526. +   // get the alpha value
  3527. +   if (a != NULL) {
  3528. +       *a = 1;
  3529. +
  3530. +       Assert(!bit_32);
  3531. +       if (!(((unsigned short*)pixel)[0] & 0x8000)) {
  3532. +           *a = 0;
  3533.         }
  3534.     }
  3535.  }
  3536.  
  3537. -void bm_page_in_xparent_texture(int bitmapnum, int nframes) {
  3538. -   int i;
  3539. +/**
  3540. +* Get filename
  3541. +*/
  3542. +void bm_get_filename(int bitmapnum, char *filename)
  3543. +{
  3544. +   if (!bm_is_valid(bitmapnum))
  3545. +   {
  3546. +       strcpy(filename, "");
  3547. +       return;
  3548. +   }
  3549. +
  3550.     int n = bitmapnum % MAX_BITMAPS;
  3551.  
  3552. -   if (n == -1)
  3553. -       return;
  3554. +   Assert(n >= 0);
  3555.  
  3556. -   Assert(bm_bitmaps[n].handle == bitmapnum);
  3557. +   // return filename
  3558. +   strcpy(filename, bm_bitmaps[n].filename);
  3559. +}
  3560. +
  3561. +/**
  3562. +* Needed only for compressed bitmaps
  3563. +*/
  3564. +int bm_is_compressed(int num)
  3565. +{
  3566. +   int n = num % MAX_BITMAPS;
  3567. +   ubyte type = BM_TYPE_NONE;
  3568. +
  3569. +   //duh
  3570. +   if (!Use_compressed_textures)
  3571. +       return 0;
  3572.  
  3573. -   for (i = 0; i < nframes; i++) {
  3574. -       bm_bitmaps[n + i].preloaded = 3;
  3575. +   Assert(n >= 0);
  3576. +   Assert(num == bm_bitmaps[n].handle);
  3577.  
  3578. -       bm_bitmaps[n + i].preload_count++;
  3579. +   type = bm_bitmaps[n].comp_type;
  3580.  
  3581. -       bm_bitmaps[n + i].used_flags = BMP_TEX_XPARENT;
  3582. +   switch (type) {
  3583. +   case BM_TYPE_NONE:
  3584. +   case BM_TYPE_DDS:
  3585. +       return 0;
  3586.  
  3587. -       //check if its compressed
  3588. -       switch (bm_bitmaps[n + i].comp_type) {
  3589. -       case BM_TYPE_NONE:
  3590. -           continue;
  3591. +   case BM_TYPE_DXT1:
  3592. +       return DDS_DXT1;
  3593.  
  3594. -       case BM_TYPE_DXT1:
  3595. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT1;
  3596. -           continue;
  3597. +   case BM_TYPE_DXT3:
  3598. +       return DDS_DXT3;
  3599.  
  3600. -       case BM_TYPE_DXT3:
  3601. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT3;
  3602. -           continue;
  3603. +   case BM_TYPE_DXT5:
  3604. +       return DDS_DXT5;
  3605.  
  3606. -       case BM_TYPE_DXT5:
  3607. -           bm_bitmaps[n + i].used_flags = BMP_TEX_DXT5;
  3608. -           continue;
  3609. +   case BM_TYPE_CUBEMAP_DXT1:
  3610. +       return DDS_CUBEMAP_DXT1;
  3611.  
  3612. -       case BM_TYPE_CUBEMAP_DXT1:
  3613. -       case BM_TYPE_CUBEMAP_DXT3:
  3614. -       case BM_TYPE_CUBEMAP_DXT5:
  3615. -           bm_bitmaps[n + i].used_flags = BMP_TEX_CUBEMAP;
  3616. -           continue;
  3617. +   case BM_TYPE_CUBEMAP_DXT3:
  3618. +       return DDS_CUBEMAP_DXT3;
  3619.  
  3620. -       default:
  3621. -           continue;
  3622. -       }
  3623. +   case BM_TYPE_CUBEMAP_DXT5:
  3624. +       return DDS_CUBEMAP_DXT5;
  3625.     }
  3626. +
  3627. +   return 0;
  3628.  }
  3629.  
  3630. -bool bm_page_out(int handle) {
  3631. +int bm_has_alpha_channel(int handle)
  3632. +{
  3633.     int n = handle % MAX_BITMAPS;
  3634.  
  3635.     Assert(n >= 0);
  3636.     Assert(handle == bm_bitmaps[n].handle);
  3637.  
  3638. -   // in case it's already been released
  3639. -   if (bm_bitmaps[n].type == BM_TYPE_NONE)
  3640. +   // assume that PCX never has a real alpha channel (it may be 32-bit, but without any alpha)
  3641. +   if (bm_bitmaps[n].type == BM_TYPE_PCX)
  3642.         return 0;
  3643.  
  3644. -   // it's possible to hit < 0 here when model_page_out_textures() is
  3645. -   // called from anywhere other than in a mission
  3646. -   if (bm_bitmaps[n].preload_count > 0) {
  3647. -       nprintf(("BmpMan",
  3648. -            "PAGE-OUT: %s - preload_count remaining: %d\n",
  3649. -            bm_bitmaps[n].filename,
  3650. -            bm_bitmaps[n].preload_count));
  3651. -
  3652. -       // lets decrease it for next time around
  3653. -       bm_bitmaps[n].preload_count--;
  3654. +   return (bm_bitmaps[n].bm.true_bpp == 32);
  3655. +}
  3656.  
  3657. -       return 0;
  3658. -   }
  3659. +/**
  3660. +* Purpose for this is to return the correct TCACHE_TYPE for compressed graphics,
  3661. +* uncompressed graphics are assumed to be of type NORMAL.
  3662. +*
  3663. +* The only other real format to check for is TCACHE_TYPE_SECTIONED - taylor
  3664. +*/
  3665. +int bm_get_tcache_type(int num)
  3666. +{
  3667. +   if (bm_is_compressed(num))
  3668. +       return TCACHE_TYPE_COMPRESSED;
  3669.  
  3670. -   return (bm_unload(handle) == 1);
  3671. +   return TCACHE_TYPE_NORMAL;
  3672.  }
  3673.  
  3674. -void bm_print_bitmaps() {
  3675. -#ifdef BMPMAN_NDEBUG
  3676. -   int i;
  3677. +int bm_get_size(int num)
  3678. +{
  3679. +   int n = num % MAX_BITMAPS;
  3680.  
  3681. -   for (i = 0; i<MAX_BITMAPS; i++) {
  3682. -       if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  3683. -           if (bm_bitmaps[i].data_size) {
  3684. -               nprintf(("BMP DEBUG", "BMPMAN = num: %d, name: %s, handle: %d - (%s) size: %.3fM\n", i, bm_bitmaps[i].filename, bm_bitmaps[i].handle, bm_bitmaps[i].data_size ? NOX("*LOCKED*") : NOX(""), ((float)bm_bitmaps[i].data_size / 1024.0f) / 1024.0f));
  3685. -           } else {
  3686. -               nprintf(("BMP DEBUG", "BMPMAN = num: %d, name: %s, handle: %d\n", i, bm_bitmaps[i].filename, bm_bitmaps[i].handle));
  3687. -           }
  3688. -       }
  3689. -   }
  3690. -   nprintf(("BMP DEBUG", "BMPMAN = LOCKED memory usage: %.3fM\n", ((float)bm_texture_ram / 1024.0f) / 1024.0f));
  3691. -#endif
  3692. +   Assert(n >= 0);
  3693. +   Assert(num == bm_bitmaps[n].handle);
  3694. +
  3695. +   return bm_bitmaps[n].mem_taken;
  3696.  }
  3697.  
  3698. -int bm_release(int handle, int clear_render_targets) {
  3699. -   Assert(handle >= 0);
  3700. +int bm_get_num_mipmaps(int num)
  3701. +{
  3702. +   int n = num % MAX_BITMAPS;
  3703.  
  3704. -   bitmap_entry *be;
  3705. +   Assert(n >= 0);
  3706. +   Assert(num == bm_bitmaps[n].handle);
  3707.  
  3708. -   int n = handle % MAX_BITMAPS;
  3709. +   if (bm_bitmaps[n].num_mipmaps == 0)
  3710. +       return 1;
  3711.  
  3712. -   Assert((n >= 0) && (n < MAX_BITMAPS));
  3713. -   be = &bm_bitmaps[n];
  3714. +   return bm_bitmaps[n].num_mipmaps;
  3715. +}
  3716.  
  3717. -   if (be->type == BM_TYPE_NONE) {
  3718. -       return 0;   // Already been released?
  3719. -   }
  3720. +/**
  3721. +* Convert an 8-bit (256 color) image to a 24-bit BGR image sending new bitmap data to "out_data"
  3722. +*/
  3723. +int bm_convert_color_index_to_BGR(int num, ubyte **out_data)
  3724. +{
  3725. +   int n = num % MAX_BITMAPS;
  3726. +   bitmap_entry *be;
  3727. +   bitmap *bmp;
  3728. +   ubyte *datap, *bgr_data = NULL, *palette = NULL;
  3729. +   char filename[MAX_FILENAME_LEN];
  3730. +   int i, j, bpp = 0, size = 0;
  3731. +   int index = 0, mult = 3;
  3732.  
  3733. -   Assertion(be->handle == handle, "Invalid bitmap handle number %d (expected %d) for %s passed to bm_release()\n", be->handle, handle, be->filename);
  3734. +   Assert(out_data != NULL);
  3735. +   Assert(n >= 0);
  3736. +   Assert(num == bm_bitmaps[n].handle);
  3737.  
  3738. -   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  3739. -       nprintf(("BmpMan", "Tried to release a render target!\n"));
  3740. -       return 0;
  3741. -   }
  3742. +   if (num != bm_bitmaps[n].handle)
  3743. +       return 1;
  3744.  
  3745. -   // If it is locked, cannot free it.
  3746. -   if (be->ref_count != 0) {
  3747. -       nprintf(("BmpMan", "Tried to release %s that has a lock count of %d.. not releasing\n", be->filename, be->ref_count));
  3748. -       return 0;
  3749. +   be = &bm_bitmaps[n];
  3750. +   bmp = &be->bm;
  3751. +
  3752. +   if ((bmp->bpp != 8) || !(bmp->data) || ((be->type != BM_TYPE_DDS) && (be->type != BM_TYPE_PCX)))
  3753. +   {
  3754. +       return 1;
  3755.     }
  3756.  
  3757. -   // kind of like ref_count except it gets around the lock/unlock usage problem
  3758. -   // this gets set for each bm_load() call so we can make sure and not unload it
  3759. -   // from memory, even if we *can*, until it's really not needed anymore
  3760. -   if (be->load_count > 0)
  3761. -       be->load_count--;
  3762. +   // it's up to the calling function to free() this but not to malloc() it!!
  3763. +   bgr_data = (ubyte*)vm_malloc_q(bmp->w * bmp->h * 3);
  3764.  
  3765. -   if (be->load_count != 0) {
  3766. -       nprintf(("BmpMan", "Tried to release %s that has a load count of %d.. not releasing\n", be->filename, be->load_count + 1));
  3767. -       return 0;
  3768. -   }
  3769. +   ubyte *in_data = (ubyte*)bmp->data;
  3770.  
  3771. -   if (be->type != BM_TYPE_USER) {
  3772. -       nprintf(("BmpMan", "Releasing bitmap %s in slot %i with handle %i\n", be->filename, n, handle));
  3773. -   }
  3774. +   if (bgr_data == NULL)
  3775. +       return 1;
  3776.  
  3777. -   // be sure that all frames of an ani are unloaded - taylor
  3778. -   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  3779. -       int i, first = be->info.ani.first_frame, total = bm_bitmaps[first].info.ani.num_frames;
  3780. +   memset(bgr_data, 0, bmp->w * bmp->h * 3);
  3781.  
  3782. -       for (i = 0; i < total; i++) {
  3783. -           bm_free_data(first + i, true);      // clears flags, bbp, data, etc
  3784. +   palette = new ubyte[1024]; // 256*4, largest size we should have to process
  3785. +   Assert(palette != NULL);
  3786.  
  3787. -           memset(&bm_bitmaps[first + i], 0, sizeof(bitmap_entry));
  3788. +   // make sure we are using the correct filename in the case of an EFF.
  3789. +   // this will populate filename[] whether it's EFF or not
  3790. +   EFF_FILENAME_CHECK;
  3791.  
  3792. -           bm_bitmaps[first + i].type = BM_TYPE_NONE;
  3793. -           bm_bitmaps[first + i].comp_type = BM_TYPE_NONE;
  3794. -           bm_bitmaps[first + i].dir_type = CF_TYPE_ANY;
  3795. -           // Fill in bogus structures!
  3796. +   if (be->type == BM_TYPE_PCX) {
  3797. +       pcx_read_header(filename, NULL, NULL, NULL, &bpp, palette);
  3798. +       mult = 3; // PCX has RGB for 256 entries
  3799. +   }
  3800. +   else if (be->type == BM_TYPE_DDS) {
  3801. +       dds_read_header(filename, NULL, NULL, NULL, &bpp, NULL, NULL, &size, palette);
  3802. +       mult = 4; // DDS has RGBX for 256 entries, 'X' being an alpha setting that we don't need
  3803. +   }
  3804. +   else {
  3805. +       // we really shouldn't be here at this point but give it another check anyway
  3806. +       delete[] palette;
  3807. +       vm_free(bgr_data);
  3808. +       return 1;
  3809. +   }
  3810.  
  3811. -           // For debugging:
  3812. -           strcpy_s(bm_bitmaps[first + i].filename, "IVE_BEEN_RELEASED!");
  3813. -           bm_bitmaps[first + i].signature = 0xDEADBEEF;                                   // a unique signature identifying the data
  3814. -           bm_bitmaps[first + i].palette_checksum = 0xDEADBEEF;                            // checksum used to be sure bitmap is in current palette
  3815. +   Assert(bpp == 8);
  3816.  
  3817. -           // bookeeping
  3818. -           bm_bitmaps[first + i].ref_count = -1;                                   // Number of locks on bitmap.  Can't unload unless ref_count is 0.
  3819. +   // we can only accept 8bits obviously, but this is actually a read error check
  3820. +   if (bpp != 8) {
  3821. +       delete[] palette;
  3822. +       vm_free(bgr_data);
  3823. +       return 1;
  3824. +   }
  3825.  
  3826. -           // Stuff needed for animations
  3827. -           bm_bitmaps[first + i].info.ani.first_frame = -1;
  3828. +   datap = bgr_data;
  3829.  
  3830. -           bm_bitmaps[first + i].handle = -1;
  3831. +   for (i = 0; i < bmp->h; i++) {
  3832. +       for (j = 0; j < bmp->w; j++) {
  3833. +           index = *in_data++;
  3834. +           *datap++ = palette[index * mult + 2];
  3835. +           *datap++ = palette[index * mult + 1];
  3836. +           *datap++ = palette[index * mult];
  3837.         }
  3838. -   } else {
  3839. -       bm_free_data(n, true);      // clears flags, bbp, data, etc
  3840. -
  3841. -       memset(&bm_bitmaps[n], 0, sizeof(bitmap_entry));
  3842. +   }
  3843.  
  3844. -       bm_bitmaps[n].type = BM_TYPE_NONE;
  3845. -       bm_bitmaps[n].comp_type = BM_TYPE_NONE;
  3846. -       bm_bitmaps[n].dir_type = CF_TYPE_ANY;
  3847. -       // Fill in bogus structures!
  3848. +   *out_data = bgr_data;
  3849.  
  3850. -       // For debugging:
  3851. -       strcpy_s(bm_bitmaps[n].filename, "IVE_BEEN_RELEASED!");
  3852. -       bm_bitmaps[n].signature = 0xDEADBEEF;                                   // a unique signature identifying the data
  3853. -       bm_bitmaps[n].palette_checksum = 0xDEADBEEF;                            // checksum used to be sure bitmap is in current palette
  3854. +   delete[] palette;
  3855.  
  3856. -       // bookeeping
  3857. -       bm_bitmaps[n].ref_count = -1;                                   // Number of locks on bitmap.  Can't unload unless ref_count is 0.
  3858. +   // no errors
  3859. +   return 0;
  3860. +}
  3861.  
  3862. -       // Stuff needed for animations
  3863. -       bm_bitmaps[n].info.ani.first_frame = -1;
  3864. +/**
  3865. +* List of all bitmaps loaded, but not necessarily in memory
  3866. +* used to debug bmpman after a mission load
  3867. +*/
  3868. +void bm_print_bitmaps()
  3869. +{
  3870. +#ifdef BMPMAN_NDEBUG
  3871. +   int i;
  3872.  
  3873. -       bm_bitmaps[n].handle = -1;
  3874. +   for (i = 0; i<MAX_BITMAPS; i++) {
  3875. +       if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  3876. +           if (bm_bitmaps[i].data_size) {
  3877. +               nprintf(("BMP DEBUG", "BMPMAN = num: %d, name: %s, handle: %d - (%s) size: %.3fM\n", i, bm_bitmaps[i].filename, bm_bitmaps[i].handle, bm_bitmaps[i].data_size ? NOX("*LOCKED*") : NOX(""), ((float)bm_bitmaps[i].data_size / 1024.0f) / 1024.0f));
  3878. +           }
  3879. +           else {
  3880. +               nprintf(("BMP DEBUG", "BMPMAN = num: %d, name: %s, handle: %d\n", i, bm_bitmaps[i].filename, bm_bitmaps[i].handle));
  3881. +           }
  3882. +       }
  3883.     }
  3884. -
  3885. -   return 1;
  3886. +   nprintf(("BMP DEBUG", "BMPMAN = LOCKED memory usage: %.3fM\n", ((float)bm_texture_ram / 1024.0f) / 1024.0f));
  3887. +#endif
  3888.  }
  3889.  
  3890. -int bm_reload(int bitmap_handle, const char* filename) {
  3891. +// this will create a render target as close to the desired resolution as possable of the following base types:
  3892. +//  - BMP_FLAG_RENDER_TARGET_STATIC
  3893. +//      static render targets are ones that you intend to draw to once or not very often in game
  3894. +//  - BMP_FLAG_RENDER_TARGET_DYNAMIC
  3895. +//     dynamic render targets are ones that you will be drawing to all the time (like once per frame)
  3896. +int bm_make_render_target(int width, int height, int flags)
  3897. +{
  3898. +   int i, n;
  3899. +   int mm_lvl = 0;
  3900. +   // final w and h may be different from passed width and height
  3901. +   int w = width, h = height;
  3902. +   ubyte bpp = 32;
  3903. +   int size = 0;
  3904. +
  3905.     if (!bm_inited)
  3906.         bm_init();
  3907.  
  3908. -   // if no file was passed then get out now
  3909. -   if ((filename == NULL) || (strlen(filename) <= 0))
  3910. -       return -1;
  3911. -
  3912. -   int bitmapnum = bitmap_handle % MAX_BITMAPS;
  3913. +   // Find an open slot (starting from the end)
  3914. +   for (n = -1, i = MAX_BITMAPS - 1; i >= 0; i--) {
  3915. +       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  3916. +           n = i;
  3917. +           break;
  3918. +       }
  3919. +   }
  3920.  
  3921. -   if (bm_bitmaps[bitmapnum].type == BM_TYPE_NONE)
  3922. +   // Out of bitmap slots
  3923. +   if (n == -1)
  3924.         return -1;
  3925.  
  3926. -   if (bm_bitmaps[bitmapnum].ref_count) {
  3927. -       nprintf(("BmpMan", "Trying to reload a bitmap that is still locked. Filename: %s, ref_count: %d", bm_bitmaps[bitmapnum].filename, bm_bitmaps[bitmapnum].ref_count));
  3928. +   if (!gr_bm_make_render_target(n, &w, &h, &bpp, &mm_lvl, flags))
  3929.         return -1;
  3930. -   }
  3931. -
  3932. -   strcpy_s(bm_bitmaps[bitmapnum].filename, filename);
  3933. -   return bitmap_handle;
  3934. -}
  3935. -
  3936. -void BM_SELECT_ALPHA_TEX_FORMAT() {
  3937. -   Gr_current_red = &Gr_ta_red;
  3938. -   Gr_current_green = &Gr_ta_green;
  3939. -   Gr_current_blue = &Gr_ta_blue;
  3940. -   Gr_current_alpha = &Gr_ta_alpha;
  3941. -
  3942. -   // setup pointers
  3943. -   bm_set_components_32 = bm_set_components_argb_32_tex;
  3944. -   // should always assume that 16-bit is the default request
  3945. -   bm_set_components = bm_set_components_argb_16_tex;
  3946. -}
  3947.  
  3948. -void BM_SELECT_SCREEN_FORMAT() {
  3949. -   Gr_current_red = &Gr_red;
  3950. -   Gr_current_green = &Gr_green;
  3951. -   Gr_current_blue = &Gr_blue;
  3952. -   Gr_current_alpha = &Gr_alpha;
  3953. -
  3954. -   // setup pointers
  3955. -   bm_set_components_32 = bm_set_components_argb_32_screen;
  3956. -   // should always assume that 16-bit is the default request
  3957. -   bm_set_components = bm_set_components_argb_16_screen;
  3958. -}
  3959. -
  3960. -void BM_SELECT_TEX_FORMAT() {
  3961. -   Gr_current_red = &Gr_t_red;
  3962. -   Gr_current_green = &Gr_t_green;
  3963. -   Gr_current_blue = &Gr_t_blue;
  3964. -   Gr_current_alpha = &Gr_t_alpha;
  3965. +   Assert(mm_lvl > 0);
  3966.  
  3967. -   // setup pointers
  3968. -   bm_set_components_32 = bm_set_components_argb_32_tex;
  3969. -   // should always assume that 16-bit is the default request
  3970. -   bm_set_components = bm_set_components_argb_16_tex;
  3971. -}
  3972. +   if (flags & BMP_FLAG_RENDER_TARGET_STATIC) {
  3973. +       // data size
  3974. +       size = (w * h * (bpp >> 3));
  3975.  
  3976. -void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
  3977. -   if (*av == 0) {
  3978. -       *((unsigned short*)pixel) = (unsigned short)Gr_current_green->mask;
  3979. -       return;
  3980. +       if (mm_lvl > 1) {
  3981. +           // include size of all mipmap levels (there should be a full chain)
  3982. +           size += (size / 3) - 1;
  3983. +       }
  3984. +
  3985. +       // make sure to count all faces if a cubemap
  3986. +       if (flags & BMP_FLAG_CUBEMAP) {
  3987. +           size *= 6;
  3988. +       }
  3989.     }
  3990.  
  3991. -   *((unsigned short*)pixel) = (unsigned short)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  3992. -   *((unsigned short*)pixel) |= (unsigned short)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  3993. -   *((unsigned short*)pixel) |= (unsigned short)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  3994. -}
  3995. +   // ensure fields are cleared out from previous bitmap
  3996. +   memset(&bm_bitmaps[n], 0, sizeof(bitmap_entry));
  3997.  
  3998. -void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
  3999. -   if (*av == 0) {
  4000. -       *((unsigned short*)pixel) = 0;
  4001. -       return;
  4002. -   }
  4003. +   bm_bitmaps[n].type = (flags & BMP_FLAG_RENDER_TARGET_STATIC) ? BM_TYPE_RENDER_TARGET_STATIC : BM_TYPE_RENDER_TARGET_DYNAMIC;
  4004. +   bm_bitmaps[n].signature = Bm_next_signature++;
  4005. +   sprintf(bm_bitmaps[n].filename, "RT_%dx%d+%d", w, h, bpp);
  4006. +   bm_bitmaps[n].bm.w = (short)w;
  4007. +   bm_bitmaps[n].bm.h = (short)h;
  4008. +   bm_bitmaps[n].bm.rowsize = (short)w;
  4009. +   bm_bitmaps[n].bm.bpp = (ubyte)bpp;
  4010. +   bm_bitmaps[n].bm.true_bpp = (ubyte)bpp;
  4011. +   bm_bitmaps[n].bm.flags = (ubyte)flags;
  4012. +   bm_bitmaps[n].bm.data = 0;
  4013. +   bm_bitmaps[n].bm.palette = NULL;
  4014. +   bm_bitmaps[n].num_mipmaps = mm_lvl;
  4015. +   bm_bitmaps[n].mem_taken = size;
  4016. +   bm_bitmaps[n].dir_type = CF_TYPE_ANY;
  4017.  
  4018. -   *((unsigned short*)pixel) = (unsigned short)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  4019. -   *((unsigned short*)pixel) |= (unsigned short)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  4020. -   *((unsigned short*)pixel) |= (unsigned short)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  4021. -   *((unsigned short*)pixel) |= (unsigned short)(Gr_current_alpha->mask);
  4022. -}
  4023. +   bm_bitmaps[n].palette_checksum = 0;
  4024. +   bm_bitmaps[n].handle = bm_get_next_handle() * MAX_BITMAPS + n;
  4025. +   bm_bitmaps[n].last_used = -1;
  4026.  
  4027. -void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
  4028. -   if (*av == 0) {
  4029. -       *((unsigned int*)pixel) = (unsigned int)Gr_current_green->mask;
  4030. -       return;
  4031. +   if (bm_bitmaps[n].mem_taken) {
  4032. +       bm_bitmaps[n].bm.data = (ptr_u)bm_malloc(n, bm_bitmaps[n].mem_taken);
  4033.     }
  4034.  
  4035. -   *((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  4036. -   *((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  4037. -   *((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  4038. +   return bm_bitmaps[n].handle;
  4039.  }
  4040.  
  4041. -void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
  4042. -   if (*av == 0) {
  4043. -       *((unsigned int*)pixel) = 0;
  4044. -       return;
  4045. -   }
  4046. +int bm_is_render_target(int bitmap_id)
  4047. +{
  4048. +   int n = bitmap_id % MAX_BITMAPS;
  4049.  
  4050. -   *((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
  4051. -   *((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
  4052. -   *((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
  4053. -   *((unsigned int*)pixel) |= (unsigned int)(Gr_current_alpha->mask);
  4054. -}
  4055. +   Assert(n >= 0);
  4056. +   Assert(bitmap_id == bm_bitmaps[n].handle);
  4057.  
  4058. -void bm_set_low_mem(int mode) {
  4059. -   Assert((mode >= 0) && (mode <= 2));
  4060. +   if (!((bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_STATIC) || (bm_bitmaps[n].type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  4061. +       return 0;
  4062. +   }
  4063.  
  4064. -   CLAMP(mode, 0, 2);
  4065. -   Bm_low_mem = mode;
  4066. +   return bm_bitmaps[n].type;
  4067.  }
  4068.  
  4069. -bool bm_set_render_target(int handle, int face) {
  4070. +int bm_set_render_target(int handle, int face)
  4071. +{
  4072.     int n = handle % MAX_BITMAPS;
  4073.  
  4074.     if (n >= 0) {
  4075. @@ -2502,7 +2888,7 @@ bool bm_set_render_target(int handle, int face) {
  4076.         if ((bm_bitmaps[n].type != BM_TYPE_RENDER_TARGET_STATIC) && (bm_bitmaps[n].type != BM_TYPE_RENDER_TARGET_DYNAMIC)) {
  4077.             // odds are that someone passed a normal texture created with bm_load()
  4078.             mprintf(("Trying to set invalid bitmap (slot: %i, handle: %i) as render target!\n", n, handle));
  4079. -           return false;
  4080. +           return 0;
  4081.         }
  4082.     }
  4083.  
  4084. @@ -2517,12 +2903,6 @@ bool bm_set_render_target(int handle, int face) {
  4085.  
  4086.             gr_screen.save_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
  4087.             gr_screen.save_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
  4088. -
  4089. -           gr_screen.save_center_w = gr_screen.center_w;
  4090. -           gr_screen.save_center_h = gr_screen.center_h;
  4091. -
  4092. -           gr_screen.save_center_offset_x = gr_screen.center_offset_x;
  4093. -           gr_screen.save_center_offset_y = gr_screen.center_offset_y;
  4094.         }
  4095.  
  4096.         if (n < 0) {
  4097. @@ -2534,13 +2914,8 @@ bool bm_set_render_target(int handle, int face) {
  4098.  
  4099.             gr_screen.max_w_unscaled_zoomed = gr_screen.save_max_w_unscaled_zoomed;
  4100.             gr_screen.max_h_unscaled_zoomed = gr_screen.save_max_h_unscaled_zoomed;
  4101. -
  4102. -           gr_screen.center_w = gr_screen.save_center_w;
  4103. -           gr_screen.center_h = gr_screen.save_center_h;
  4104. -
  4105. -           gr_screen.center_offset_x = gr_screen.save_center_offset_x;
  4106. -           gr_screen.center_offset_y = gr_screen.save_center_offset_y;
  4107. -       } else {
  4108. +       }
  4109. +       else {
  4110.             gr_screen.max_w = bm_bitmaps[n].bm.w;
  4111.             gr_screen.max_h = bm_bitmaps[n].bm.h;
  4112.  
  4113. @@ -2549,12 +2924,6 @@ bool bm_set_render_target(int handle, int face) {
  4114.  
  4115.             gr_screen.max_w_unscaled_zoomed = bm_bitmaps[n].bm.w;
  4116.             gr_screen.max_h_unscaled_zoomed = bm_bitmaps[n].bm.h;
  4117. -
  4118. -           gr_screen.center_w = bm_bitmaps[n].bm.w;
  4119. -           gr_screen.center_h = bm_bitmaps[n].bm.h;
  4120. -
  4121. -           gr_screen.center_offset_x = 0;
  4122. -           gr_screen.center_offset_y = 0;
  4123.         }
  4124.  
  4125.         gr_screen.rendering_to_face = face;
  4126. @@ -2567,184 +2936,8 @@ bool bm_set_render_target(int handle, int face) {
  4127.             opengl_setup_viewport();
  4128.         }
  4129.  
  4130. -       return true;
  4131. -   }
  4132. -
  4133. -   return false;
  4134. -}
  4135. -
  4136. -int bm_unload(int handle, int clear_render_targets, bool nodebug) {
  4137. -   bitmap_entry *be;
  4138. -   bitmap *bmp;
  4139. -
  4140. -   int n = handle % MAX_BITMAPS;
  4141. -
  4142. -   Assert((n >= 0) && (n < MAX_BITMAPS));
  4143. -   be = &bm_bitmaps[n];
  4144. -   bmp = &be->bm;
  4145. -
  4146. -   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  4147. -       return -1;
  4148. -   }
  4149. -
  4150. -   if (be->type == BM_TYPE_NONE) {
  4151. -       return -1;      // Already been released
  4152. -   }
  4153. -
  4154. -   Assert(be->handle == handle);       // INVALID BITMAP HANDLE!
  4155. -
  4156. -   // If it is locked, cannot free it.
  4157. -   if (be->ref_count != 0 && !nodebug) {
  4158. -       nprintf(("BmpMan", "Tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
  4159. -       return 0;
  4160. -   }
  4161. -
  4162. -   // kind of like ref_count except it gets around the lock/unlock usage problem
  4163. -   // this gets set for each bm_load() call so we can make sure and not unload it
  4164. -   // from memory, even if we *can*, until it's really not needed anymore
  4165. -   if (!Bm_ignore_load_count) {
  4166. -       if (be->load_count > 0)
  4167. -           be->load_count--;
  4168. -
  4169. -       if (be->load_count != 0 && !nodebug) {
  4170. -           nprintf(("BmpMan", "Tried to unload %s that has a load count of %d.. not unloading\n", be->filename, be->load_count + 1));
  4171. -           return 0;
  4172. -       }
  4173. -   }
  4174. -
  4175. -   // be sure that all frames of an ani are unloaded - taylor
  4176. -   if ((be->type == BM_TYPE_ANI) || (be->type == BM_TYPE_EFF)) {
  4177. -       int i, first = be->info.ani.first_frame;
  4178. -
  4179. -       // for the unload all case, don't try to unload every frame of every frame
  4180. -       // all additional frames automatically get unloaded with the first one
  4181. -       if ((n > be->info.ani.first_frame) && (bm_bitmaps[first].bm.data == 0))
  4182. -           return 1;
  4183. -
  4184. -       for (i = 0; i < bm_bitmaps[first].info.ani.num_frames; i++) {
  4185. -           if (!nodebug)
  4186. -               nprintf(("BmpMan", "Unloading %s frame %d.  %dx%dx%d\n", be->filename, i, bmp->w, bmp->h, bmp->bpp));
  4187. -           bm_free_data(first + i);        // clears flags, bbp, data, etc
  4188. -       }
  4189. -   } else {
  4190. -       if (!nodebug)
  4191. -           nprintf(("BmpMan", "Unloading %s.  %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
  4192. -       bm_free_data(n);        // clears flags, bbp, data, etc
  4193. -   }
  4194. -
  4195. -   return 1;
  4196. -}
  4197. -
  4198. -void bm_unload_all() {
  4199. -   int i;
  4200. -
  4201. -   // since bm_unload_all() should only be called from game_shutdown() it should be
  4202. -   // safe to ignore load_count's and unload anyway
  4203. -   Bm_ignore_load_count = 1;
  4204. -
  4205. -   for (i = 0; i < MAX_BITMAPS; i++) {
  4206. -       if (bm_bitmaps[i].type != BM_TYPE_NONE) {
  4207. -           bm_unload(bm_bitmaps[i].handle, 1);
  4208. -       }
  4209. -   }
  4210. -
  4211. -   Bm_ignore_load_count = 0;
  4212. -}
  4213. -
  4214. -int bm_unload_fast(int handle, int clear_render_targets) {
  4215. -   bitmap_entry *be;
  4216. -   bitmap *bmp;
  4217. -
  4218. -   int n = handle % MAX_BITMAPS;
  4219. -
  4220. -   Assert((n >= 0) && (n < MAX_BITMAPS));
  4221. -   be = &bm_bitmaps[n];
  4222. -   bmp = &be->bm;
  4223. -
  4224. -   if (be->type == BM_TYPE_NONE) {
  4225. -       return -1;      // Already been released
  4226. -   }
  4227. -
  4228. -   if (be->type == BM_TYPE_USER) {
  4229. -       return -1;
  4230. -   }
  4231. -
  4232. -   if (!clear_render_targets && ((be->type == BM_TYPE_RENDER_TARGET_STATIC) || (be->type == BM_TYPE_RENDER_TARGET_DYNAMIC))) {
  4233. -       return -1;
  4234. -   }
  4235. -
  4236. -   // If it is locked, cannot free it.
  4237. -   if (be->ref_count != 0) {
  4238. -       nprintf(("BmpMan", "Tried to unload_fast %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
  4239. -       return 0;
  4240. -   }
  4241. -
  4242. -   Assert(be->handle == handle);       // INVALID BITMAP HANDLE!
  4243. -
  4244. -   // unlike bm_unload(), we handle each frame of an animation separately, for safer use in the graphics API
  4245. -   nprintf(("BmpMan", "Fast-unloading %s.  %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
  4246. -   bm_free_data_fast(n);       // clears flags, bbp, data, etc
  4247. -
  4248. -   return 1;
  4249. -}
  4250. -
  4251. -void bm_unlock(int handle) {
  4252. -   bitmap_entry    *be;
  4253. -
  4254. -   if (!bm_inited) bm_init();
  4255. -
  4256. -   int bitmapnum = handle % MAX_BITMAPS;
  4257. -
  4258. -#ifndef NDEBUG
  4259. -   if (bm_bitmaps[bitmapnum].handle != handle) {
  4260. -       mprintf(("bm_unlock - %s: bm_bitmaps[%d].handle = %d, handle = %d\n", bm_bitmaps[bitmapnum].filename, bitmapnum, bm_bitmaps[bitmapnum].handle, handle));
  4261. -   }
  4262. -#endif
  4263. -
  4264. -   Assert(bm_bitmaps[bitmapnum].handle == handle); // INVALID BITMAP HANDLE
  4265. -
  4266. -   Assert((bitmapnum >= 0) && (bitmapnum < MAX_BITMAPS));
  4267. -
  4268. -   be = &bm_bitmaps[bitmapnum];
  4269. -
  4270. -   be->ref_count--;
  4271. -   Assert(be->ref_count >= 0);     // Trying to unlock data more times than lock was called!!!
  4272. -}
  4273. -
  4274. -void bm_update_memory_used(int n, int size)
  4275. -{
  4276. -   Assert( (n >= 0) && (n < MAX_BITMAPS) );
  4277. -   Assert( size >= 0 );
  4278. -
  4279. -#ifdef BMPMAN_NDEBUG
  4280. -   Assert( bm_bitmaps[n].data_size == 0 );
  4281. -   bm_bitmaps[n].data_size += size;
  4282. -   bm_texture_ram += size;
  4283. -#endif
  4284. -}
  4285. -
  4286. -int find_block_of(int n)
  4287. -{
  4288. -   int i, cnt = 0, nstart = 0;
  4289. -
  4290. -   if (n < 1) {
  4291. -       Int3();
  4292. -       return -1;
  4293. -   }
  4294. -
  4295. -   for (i = 0; i < MAX_BITMAPS; i++) {
  4296. -       if (bm_bitmaps[i].type == BM_TYPE_NONE) {
  4297. -           if (cnt == 0)
  4298. -               nstart = i;
  4299. -
  4300. -           cnt++;
  4301. -       } else {
  4302. -           cnt = 0;
  4303. -       }
  4304. -
  4305. -       if (cnt == n)
  4306. -           return nstart;
  4307. +       return 1;
  4308.     }
  4309.  
  4310. -   return -1;
  4311. +   return 0;
  4312.  }
  4313. diff --git a/code/bmpman/bmpman.h b/code/bmpman/bmpman.h
  4314. index f547d01..edcd40d 100644
  4315. --- a/code/bmpman/bmpman.h
  4316. +++ b/code/bmpman/bmpman.h
  4317. @@ -1,674 +1,275 @@
  4318. +/*
  4319. +* Copyright (C) Volition, Inc. 1999.  All rights reserved.
  4320. +*
  4321. +* All source code herein is the property of Volition, Inc. You may not sell
  4322. +* or otherwise commercially exploit the source or things you created based on the
  4323. +* source.
  4324. +*
  4325. +*/
  4326. +
  4327. +
  4328. +
  4329.  #ifndef _BMPMAN_H
  4330.  #define _BMPMAN_H
  4331. -/*
  4332. - * Copyright (C) Volition, Inc. 1999.  All rights reserved.
  4333. - *
  4334. - * All source code herein is the property of Volition, Inc. You may not sell
  4335. - * or otherwise commercially exploit the source or things you created based on the
  4336. - * source.
  4337. - *
  4338. - */
  4339. -
  4340. -/**
  4341. - * @file bmpman.h
  4342. - * Header file for the bitmap manager (bmpman)
  4343. - */
  4344. -
  4345. -/**
  4346. - * @example bm_examples.cpp
  4347. - * @brief This containes examples of bmpman usage
  4348. - */
  4349.  
  4350. -#include "cfile/cfile.h"
  4351.  #include "globalincs/pstypes.h"
  4352. +#include "cfile/cfile.h"
  4353.  
  4354.  #ifndef NDEBUG
  4355. -#define BMPMAN_NDEBUG  //!< Enables BMPMAN debugging code
  4356. +#define BMPMAN_NDEBUG
  4357.  #endif
  4358.  
  4359. -/**
  4360. - * @defgroup BMPMAN_CONSTANTS Macro constants used in/with bmpman.h
  4361. - *
  4362. - * @{
  4363. - */
  4364. -
  4365. -/**
  4366. - * @brief How many bitmaps the game can handle
  4367. - *
  4368. - * @attention  MAX_BITMAPS shouldn't need to be bumped again.  With the fixed bm_release() and it's proper use even the
  4369. - *   largest missions should stay under this number.  With the largest retail missions and wasteful content we should
  4370. - *   still have about 20% of the slots free.  If it still goes over then it's something the artists need to fix.
  4371. - *   For instance the Terran Mara fighter, with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.
  4372. - *   111 of those is just for the glowmaps.  This number can be greatly reduced if the number of ani frames for another
  4373. - *   LOD than LOD0 has fewer or no ani frames.  A 37 frame glow ani for LOD2 is little more than a waste of resources.
  4374. - *   Future reports of texture corruption should be initially approached with content as the cause and not code.
  4375. - *   If anything we could/should reduce MAX_BITMAPS in the future.  Where it's at now should accomidate even the
  4376. - *   largest mods.  --  Taylor
  4377. - */
  4378. -#define MAX_BITMAPS 4750
  4379. -
  4380. -// Flag positions for bitmap.flags
  4381. +#define MAX_BITMAPS 4750           // How many bitmaps the game can handle
  4382. +// NOTE:  MAX_BITMAPS shouldn't need to be bumped again.  With the fixed bm_release() and it's
  4383. +// proper use even the largest missions should stay under this number.  With the largest retail
  4384. +// missions and wasteful content we should still have about 20% of the slots free.  If it still
  4385. +// goes over then it's something the artists need to fix.  For instance the Terran Mara fighter,
  4386. +// with -spec and -glow and using the Shinepack, needs 117 bitmap slots alone.  111 of those is
  4387. +// just for the glowmaps.  This number can be greatly reduced if the number of ani frames for
  4388. +// another LOD than LOD0 has fewer or no ani frames.  A 37 frame glow ani for LOD2 is little
  4389. +// more than a waste of resources.  Future reports of texture corruption should be initially
  4390. +// approached with content as the cause and not code.  If anything we could/should reduce
  4391. +// MAX_BITMAPS in the future.  Where it's at now should accomidate even the largest mods.
  4392. +//  --  Taylor
  4393. +
  4394. +
  4395. +#define    BMP_AABITMAP                        (1<<0)              // antialiased bitmap
  4396. +#define    BMP_TEX_XPARENT                     (1<<1)              // transparent texture
  4397. +#define    BMP_TEX_OTHER                       (1<<2)              // so we can identify all "normal" textures
  4398. +#define BMP_TEX_DXT1                       (1<<3)              // dxt1 compressed 8r8g8b1a (24bit)
  4399. +#define BMP_TEX_DXT3                       (1<<4)              // dxt3 compressed 8r8g8b4a (32bit)
  4400. +#define BMP_TEX_DXT5                       (1<<5)              // dxt5 compressed 8r8g8b8a (32bit)
  4401. +#define BMP_TEX_CUBEMAP                        (1<<6)              // a texture made for cubic environment map
  4402.  // ***** NOTE:  bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
  4403. -#define    BMP_AABITMAP        (1<<0)      //!< antialiased bitmap
  4404. -#define    BMP_TEX_XPARENT     (1<<1)      //!< transparent texture
  4405. -#define    BMP_TEX_OTHER       (1<<2)      //!< so we can identify all "normal" textures
  4406. -#define BMP_TEX_DXT1        (1<<3)      //!< dxt1 compressed 8r8g8b1a (24bit)
  4407. -#define BMP_TEX_DXT3        (1<<4)      //!< dxt3 compressed 8r8g8b4a (32bit)
  4408. -#define BMP_TEX_DXT5        (1<<5)      //!< dxt5 compressed 8r8g8b8a (32bit)
  4409. -#define BMP_TEX_CUBEMAP     (1<<6)      //!< a texture made for cubic environment map
  4410. -
  4411. -// Combined flags
  4412. -#define BMP_TEX_COMP        ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 )  //!< Compressed textures
  4413. -#define BMP_TEX_NONCOMP     ( BMP_TEX_XPARENT | BMP_TEX_OTHER )             //!< Non-compressed textures
  4414. -#define    BMP_TEX_ANY         ( BMP_TEX_COMP | BMP_TEX_NONCOMP )              //!< Any texture
  4415. -
  4416. -// Flag positions for bitmap.type
  4417. -#define BMP_FLAG_RENDER_TARGET_STATIC       (1<<0)      //!< Texture is a static type
  4418. -#define BMP_FLAG_RENDER_TARGET_DYNAMIC      (1<<1)      //!< Texture is a dynamic type (animation)
  4419. -#define BMP_FLAG_CUBEMAP                    (1<<2)      //!< Texture is a cubemap
  4420. -
  4421. -// Bitmap types
  4422. -enum BM_TYPE
  4423. -{
  4424. -   BM_TYPE_NONE = 0,   //!< No type
  4425. -   BM_TYPE_USER,       //!< in-memory
  4426. -   BM_TYPE_PCX,        //!< PCX
  4427. -   BM_TYPE_TGA,        //!< 16 or 32 bit targa
  4428. -   BM_TYPE_DDS,        //!< generic identifier for DDS
  4429. -   BM_TYPE_PNG,        //!< PNG
  4430. -   BM_TYPE_JPG,        //!< 32 bit jpeg
  4431. -   BM_TYPE_ANI,        //!< in-house ANI format
  4432. -   BM_TYPE_EFF,        //!< specifies any type of animated image, the EFF itself is just text
  4433. -
  4434. -   // special types
  4435. -   BM_TYPE_RENDER_TARGET_STATIC,   //!< 24/32 bit setup internally as a static render target
  4436. -   BM_TYPE_RENDER_TARGET_DYNAMIC,  //!< 24/32 bit setup internally as a dynamic render target
  4437. -
  4438. -   // Compressed types (bitmap.c_type)
  4439. -   BM_TYPE_DXT1,           //!< 24 bit with switchable alpha
  4440. -   BM_TYPE_DXT3,           //!< 32 bit with 4 bit alpha
  4441. -   BM_TYPE_DXT5,           //!< 32 bit with 8 bit alpha
  4442. -   BM_TYPE_CUBEMAP_DDS,    //!< generic DDS cubemap (uncompressed cubemap surface)
  4443. -   BM_TYPE_CUBEMAP_DXT1,   //!< 24-bit cubemap        (compressed cubemap surface)
  4444. -   BM_TYPE_CUBEMAP_DXT3,   //!< 32-bit cubemap        (compressed cubemap surface)
  4445. -   BM_TYPE_CUBEMAP_DXT5    //!< 32-bit cubemap        (compressed cubemap surface)
  4446. -};
  4447. -
  4448. -/**
  4449. - * @}
  4450. - */
  4451. -
  4452. -struct bitmap
  4453. -{
  4454. -   short   w;          //!< Width, in number of pixels
  4455. -   short   h;          //!< Height, in number of pixels
  4456. -   short   rowsize;    //!< What you need to add to go to next row
  4457. -   ubyte   bpp;        //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
  4458. -   ubyte   true_bpp;   //!< The image's actual bitdepth
  4459. -   ubyte   flags;      //!< Various texture type flags. @see BMPMAN_CONSTANTS
  4460. -   ptr_u   data;       //!< Pointer to data, or maybe offset into VRAM.
  4461. -   ubyte *palette;     /**< @brief   Pointer to this bitmap's palette (if it has one).
  4462. -                        *   @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
  4463. -                        */
  4464. -};
  4465. -
  4466. -extern int bm_texture_ram;  //!< how many bytes of textures are used.
  4467. -
  4468. -extern int Bm_paging;   //!< Bool type that indicates if BMPMAN is currently paging.
  4469. -
  4470. -extern const BM_TYPE bm_type_list[];       //!< List of valid bitmap types
  4471. -extern const char *bm_ext_list[];        //!< List of extensions for those types
  4472. -extern const int BM_NUM_TYPES;           //!< Calculated number of bitmap types
  4473. -extern const BM_TYPE bm_ani_type_list[];   //!< List of valid bitmap animation types
  4474. -extern const char *bm_ani_ext_list[];    //!< List of extensions for those types
  4475. -extern const int BM_ANI_NUM_TYPES;       //!< Calculated number of bitmap animation types
  4476. -
  4477. -extern int GLOWMAP;     //!< References a map that is a fully lit version of its index -Bobboau
  4478. -extern int SPECMAP;     //!< References a map that is for specular mapping -Bobboau
  4479. -extern int ENVMAP;      //!< References a map that is for environment mapping -Bobboau
  4480. -extern int NORMMAP;     //!< Normal mapping
  4481. -extern int HEIGHTMAP;   //!< Height map for normal mapping
  4482. -extern int MISCMAP;     //!< Utility map, to be utilized for various things shader authors can come up with
  4483. -
  4484. -/**
  4485. - * @brief Initilizes the bitmap manager
  4486. - */
  4487. +
  4488. +//compressed texture types
  4489. +#define BMP_TEX_COMP           ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 )
  4490. +
  4491. +//non compressed textures
  4492. +#define BMP_TEX_NONCOMP            ( BMP_TEX_XPARENT | BMP_TEX_OTHER )
  4493. +
  4494. +// any texture type
  4495. +#define    BMP_TEX_ANY             ( BMP_TEX_COMP | BMP_TEX_NONCOMP )
  4496. +
  4497. +#define BMP_FLAG_RENDER_TARGET_STATIC      (1<<0)
  4498. +#define BMP_FLAG_RENDER_TARGET_DYNAMIC     (1<<1)
  4499. +#define BMP_FLAG_CUBEMAP                   (1<<2)
  4500. +
  4501. +typedef struct bitmap {
  4502. +   int     id;         // defines a bitmap ID
  4503. +   short   w, h;       // Width and height
  4504. +   short   rowsize;    // What you need to add to go to next row
  4505. +   ubyte   bpp;        // How many bits per pixel it is. (7,8,15,16,24,32) (what is requested)
  4506. +   ubyte   true_bpp;   // How many bits per pixel the image actually is.
  4507. +   ubyte   flags;      // See the BMP_???? defines for values (this isn't for the BMP_FLAG_* stuff)
  4508. +   ptr_u   data;       // Pointer to data, or maybe offset into VRAM.
  4509. +   ubyte *palette;     // If bpp==8, this is pointer to palette.   If the BMP_NO_PALETTE_MAP flag
  4510. +                       // is not set, this palette just points to the screen palette. (gr_palette)
  4511. +} bitmap;
  4512. +
  4513. +
  4514. +extern int Bm_paging;
  4515. +
  4516.  void bm_init();
  4517.  
  4518. -/**
  4519. - * @brief Closes the bitmap manager, freeing any allocated memory used by bitmaps. Is called at program close.
  4520. - */
  4521.  void bm_close();
  4522.  
  4523. -/**
  4524. - * Gets the cache slot of the bitmap indexed by handle.
  4525. - *
  4526. - * @details if the bitmap is an ani, gets the first frame
  4527. - *
  4528. - * @returns The cache slot index of the bitmap if handle is valid
  4529. - *
  4530. - * @note If the handle is invalid, an Assert() fails
  4531. - */
  4532.  int bm_get_cache_slot(int bitmap_id, int separate_ani_frames);
  4533.  
  4534. -/**
  4535. - * @brief Gets the next available bitmap slot.
  4536. - */
  4537.  int bm_get_next_handle();
  4538.  
  4539. -/**
  4540. - * @brief Allocates memory for the given handle.
  4541. - *
  4542. - * @returns A pointer to the allocated vm if successful,
  4543. - * @returns Null, if unsuccessful
  4544. - *
  4545. - * @note z64 - This function looks fishy. Not only is handle not used in release builds, but bm_bitmaps[handle].size
  4546. - *   and bm_texture_size aren't modified unless this is a debug build
  4547. - */
  4548. -void *bm_malloc(int handle, int size);
  4549. -
  4550. -/**
  4551. - * @brief (DEBUG) Similar to bm_malloc, but only updates how much memory is used
  4552. - *
  4553. - * @note z64 - Also fishy (see bm_malloc)
  4554. - */
  4555.  void bm_update_memory_used(int n, int size);
  4556.  
  4557. -class bitmap_lookup {
  4558. -   float *Bitmap_data;
  4559. -
  4560. -   int Width;
  4561. -   int Height;
  4562. -   int Num_channels;
  4563. -
  4564. -   float map_texture_address(float address);
  4565. -public:
  4566. -   bitmap_lookup(int bitmap_num);
  4567. -   ~bitmap_lookup();
  4568. -
  4569. -   bool valid();
  4570. -
  4571. -   float get_channel_red(float u, float v);
  4572. -   float get_channel_green(float u, float v);
  4573. -   float get_channel_blue(float u, float v);
  4574. -   float get_channel_alpha(float u, float v);
  4575. -};
  4576. -
  4577. -/**
  4578. - * @brief Loads a bitmap so we can draw with it later.
  4579. - *
  4580. - * @param filename
  4581. - *
  4582. - * @returns The bitmap number if successful, else
  4583. - * @returns a negative value if not
  4584. - */
  4585. -int bm_load(const char* filename);
  4586. +// how many bytes of textures are used.
  4587. +extern int bm_texture_ram;
  4588.  
  4589. -/**
  4590. - * @brief Loads a bitmap so we can draw with it later. (Preferred version)
  4591. - *
  4592. - * @param filename
  4593. - *
  4594. - * @returns The bitmap number if successful, else
  4595. - * @returns a negative value if not
  4596. - */
  4597. +// This loads a bitmap so we can draw with it later.
  4598. +// It returns a negative number if it couldn't load
  4599. +// the bitmap.   On success, it returns the bitmap
  4600. +// number.
  4601. +int bm_load(const char* filename);
  4602.  int bm_load(const SCP_string& filename);
  4603.  
  4604. -/**
  4605. - * @brief Reloads a bitmap as a duplicate.
  4606. - *
  4607. - * @details This function basically allows you to load a bitmap which already exists (by filename). This is useful
  4608. - *   because in some cases we need to have a bitmap which is locked in screen format _and_ texture format, such as
  4609. - *   the pilot pics and squad logos
  4610. - *
  4611. - * @param filename
  4612. - *
  4613. - * @returns The bitmap number if successful, else
  4614. - * @returns a negative value if not
  4615. - */
  4616. +// special load function. basically allows you to load a bitmap which already exists (by filename).
  4617. +// this is useful because in some cases we need to have a bitmap which is locked in screen format
  4618. +// _and_ texture format, such as pilot pics and squad logos
  4619.  int bm_load_duplicate(const char *filename);
  4620.  
  4621. -/**
  4622. - * Loads a bitmap which exists somewhere in the RAM.
  4623. - *
  4624. - * @param bpp The bitdepth of the bitmap
  4625. - * @param w The width of the bitmap
  4626. - * @param h The height of the bitmap
  4627. - * @param[in] data The bitmap's data glob
  4628. - * @param flags
  4629. - *
  4630. - * @note The used RAM cannot be freed until bm_release is called on the created bitmap
  4631. - */
  4632. +// Creates a bitmap that exists in RAM somewhere, instead
  4633. +// of coming from a disk file.  You pass in a pointer to a
  4634. +// block of data.  The data can be in the following formats:
  4635. +// 8 bpp (mapped into game palette)
  4636. +// 32 bpp
  4637. +// On success, it returns the bitmap number.  You cannot
  4638. +// free that RAM until bm_release is called on that bitmap.  
  4639. +// See example at bottom of this file
  4640.  int bm_create(int bpp, int w, int h, void *data = NULL, int flags = 0);
  4641.  
  4642. -/**
  4643. - * @brief Unloads a bitmap's data, but not the bitmap info
  4644. - *
  4645. - * @details The bm number (n) may be reused once this function has been called on it. However, it will have to be paged
  4646. - *   in the next time it is locked.
  4647. -
  4648. - * @param handle                The index number of the bitmap to free
  4649. - * @param clear_render_targets  If true, release a render target
  4650. - * @param nodebug               If true, exclude certain debug messages
  4651. - *
  4652. - * @returns 0 if not successful,
  4653. - * @returns 1 if successful
  4654. - */
  4655. -int bm_unload(int handle, int clear_render_targets = 0, bool nodebug = false);
  4656. -
  4657. -/**
  4658. - * @brief Quickly unloads a bitmap's data, ignoring the load_count
  4659. - *
  4660. - * @details Similar to bm_unload(), except that it can be safely used to free data without worrying about load_count.
  4661. - *   It's safe to use in relation to bm_release() and in gr_*_texture functions
  4662. - *
  4663. - * @param handle                The bm number of the bitmap to free
  4664. - * @param clear_render_targets  If true, release a render target
  4665. - *
  4666. - * @note bm_free_data_fast() is used here and NOT bm_free_data()
  4667. - */
  4668. -int bm_unload_fast(int handle, int clear_render_targets = 0);
  4669. -
  4670. -/**
  4671. - * @brief Frees both a bitmap's data and it's associated slot.
  4672. - *
  4673. - * @details Once called, the bm number 'n' cannot be used until bm_load or bm_create is re-inits the slot.
  4674. - *
  4675. - * @param handle               The index number of the bitmap to release
  4676. - * @param clear_render_targets If nonzero, also release render targets
  4677. - *
  4678. - * @returns 1 on success,
  4679. - * @returns 0 otherwise
  4680. - *
  4681. - * @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!
  4682. - *
  4683. - * @todo upgrade return type and clear_render_targets type to bools
  4684. - */
  4685. -int bm_release(int handle, int clear_render_targets = 0);
  4686. -
  4687. -/**
  4688. - * @brief Loads a bitmap sequance so we can draw with it.
  4689. - *
  4690. - * @param[in] filename
  4691. - * @param[out] nframes          If non-null, set to the number of frames the animation has
  4692. - * @param[out] fps              If non-null, set to the fps of this animation
  4693. - * @param[out] keyframe         if non null, set to the keyframe index of this animation
  4694. - * @param[in] can_drop_frames   If set, allows dropped frames
  4695. - * @param[in] dir_type          Directory type
  4696. - *
  4697. - * @returns The bm number of the first bitmap in the sequence if successful, or
  4698. - * @returns A negative value if unsuccessful
  4699. - */
  4700. -int bm_load_animation(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
  4701. -
  4702. -/**
  4703. - * @brief Loads either animation (bm_load_animation) or still image (bm_load)
  4704. - *
  4705. - * @param[in] filename
  4706. - * @param[out] nframes  If non-null and loading was successful, set to the number of frames the animation has
  4707. - * @param[out] fps      If non-null and loading was successful, set to the fps of this animation
  4708. - * @param[out] keyframe if non null and loading was successful, set to the keyframe index of this animation
  4709. - * @param[in] can_drop_frames
  4710. - * @param[in] dir_type
  4711. - *
  4712. - * @returns The bm number of the first bitmap in the sequence if successful, or
  4713. - * @returns A negative value if unsuccessful
  4714. - */
  4715. -int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
  4716. -
  4717. -/**
  4718. - * @brief Locks down the bitmap indexed by bitmapnum.
  4719. - *
  4720. - * @details Also converts the bitmap to the appropriate format specified by bpp and flags. Only lock a bitmap when you
  4721. - *   need it!
  4722. - *
  4723. - * @param handle    The number indexing the desired bitmap
  4724. - * @param bpp       The desired bpp of the bitmep
  4725. - * @param flags     The desired bitmap format
  4726. - * @param nodebug
  4727. -
  4728. - * @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
  4729. - * @returns NULL if unsuccessful
  4730. - */
  4731. -bitmap* bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug = false);
  4732. -
  4733. -/**
  4734. - * @brief Returns a unique signiature for the bitmap indexed by handle
  4735. - *
  4736. - * @details A signature will change when the bitmap's data changes
  4737. - */
  4738. -uint bm_get_signature(int handle);
  4739. -
  4740. -/**
  4741. - * @brief Returns the image type of the given bitmap handle
  4742. - */
  4743. -BM_TYPE bm_get_type(int handle);
  4744. -
  4745. -/**
  4746. - * @brief Unlocks a bitmap
  4747. - *
  4748. - * @details Decrements the ref_count member of the bitmap_entry struct, A bitmap can only be unloaded when the
  4749. - * ref_count is 0
  4750. - */
  4751. -void bm_unlock(int handle);
  4752. -
  4753. -/**
  4754. - * @brief Checks if the bitmap indexed by handle is valid
  4755. - *
  4756. - * @details Some early known false or out of range handles (such as negative) are checked within
  4757. - * an initial routine pass, followed by a more thorough check routine to ensure the
  4758. - * series of bitmaps within the bm_bitmaps[] structure have not become invalid.
  4759. - *
  4760. - * @returns Nonzero if valid, else
  4761. - * @returns Zero otherwise
  4762. - *
  4763. - * @todo z64 - Returned value is essentially a bool type, need to check all caller functions to see if it can safely
  4764. - *   be updated to reflect this
  4765. - */
  4766. -int bm_is_valid(int handle);
  4767. -
  4768. -/**
  4769. - * @brief Gets info on the bitmap indexed by handle.
  4770. - *
  4771. - * @param[out] w      If non-null, gets the width
  4772. - * @param[out] h      If non-null, gets the heigth
  4773. - * @param[out] flags  If non-null, gets the flags
  4774. - * @param[out] nframs If non-null, gets the nframes
  4775. - * @param[out] fps    If non-null, gets the fps
  4776. - *
  4777. - * @returns The handle on success, or
  4778. - * @returns The handle to the first frame on success, or
  4779. - * @returns -1 on failure
  4780. - */
  4781. -int bm_get_info(int handle, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
  4782. -
  4783. -/**
  4784. - * @brief Gets the filename of the bitmap indexed by handle
  4785. - *
  4786. - * @param[out] filename The filename of the bitmap, if successful. Is set to an empty string if unseccessful
  4787. - *
  4788. - * @todo z64 - maybe deprecate this in favor of an SCP_string version
  4789. - */
  4790. -void bm_get_filename(int bitmapnum, char *filename);
  4791. -
  4792. -/**
  4793. - * @brief Gets the filename of the bitmap indexed by handle, which must exist.
  4794. - *
  4795. - * @details If the bitmap does not exist (i.e. the handle is invalid), then an Assertion halts program execution.
  4796. - *
  4797. - * @returns A const char* to the filename of the bitmap
  4798. - *
  4799. - * @todo z64 - maybe deprecate this in favor of an SCP_string version.
  4800. - * @todo z64 - maybe combine this with the other bm_get_filename function like so:
  4801. - *   void bm_get_filename(int handle, SCP_string *filename, bool must_exist = false);
  4802. - */
  4803. -const char *bm_get_filename(int handle);
  4804. +// Frees up a bitmap's data, but bitmap number 'n' can
  4805. +// still be used, it will just have to be paged in next
  4806. +// time it is locked.
  4807. +int bm_unload(int n, int clear_render_targets = 0, bool nodebug = false);
  4808. +
  4809. +// like bm_unload() except that it's safe to use to free data without worrying about
  4810. +// load_count so it's safe to use in relation to bm_release() and in gr_*_texture functions
  4811. +int bm_unload_fast(int n, int clear_render_targets = 0);
  4812. +
  4813. +// Frees up a bitmap's data, and it's slot, so bitmap
  4814. +// number 'n' cannot be used anymore, and bm_load or
  4815. +// bm_create might reuse the slot.
  4816. +int bm_release(int n, int clear_render_targets = 0);
  4817. +
  4818. +// This loads a bitmap sequence so we can draw with it later.
  4819. +// It returns a negative number if it couldn't load
  4820. +// the bitmap.   On success, it returns the bitmap
  4821. +// number of the first frame and nframes is set.
  4822. +extern int bm_load_animation(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
  4823.  
  4824. -/**
  4825. - * @brief Loads all data for all bitmaps that have been requested to be loaded
  4826. - *
  4827. - * @note This function is not defined.
  4828. - */
  4829. -void bm_gfx_load_all();
  4830. -
  4831. -/**
  4832. - * @brief Unloads all used bitmaps, should only ever be called by game_shutdown()
  4833. - *
  4834. - * @todo Maybe move this declaration into bmpman.cpp and then extern this function within game_shutdown() to
  4835. - *  ensure it only ever gets called there.
  4836. - */
  4837. -void bm_unload_all();
  4838. -
  4839. -/**
  4840. - * @brief Gets the palette for a given bitmap indexed by handle, and optionally the filename
  4841. - *
  4842. - * @param[out] pal Is set to reference the bitmap's palette
  4843. - * @param[out] name (optional) Is set to the bitmap's filename
  4844. - *
  4845. - * @todo Maybe get rid of the optional filename and have the callers call bm_get_filename. Less efficient, however.
  4846. - */
  4847. -void bm_get_palette(int handle, ubyte *pal, char *name);
  4848. -
  4849. -/**
  4850. - * @brief Hack to get a pixel from a bitmap
  4851. - *
  4852. - * @details only works good in 8bpp mode
  4853. - *
  4854. - * @note This function is not defined.
  4855. - */
  4856. -void bm_gfx_get_pixel(int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *b);
  4857. -
  4858. -/**
  4859. - * @brief (DEBUG) Gets memory size, in bytes, of the locked bitmaps
  4860. - *
  4861. - * @details Both params are non-optional, and must be non-null. There's currently no safety checks on either.
  4862. - *
  4863. - * @param ntotal[out] Memory size, in bytes, of the locked bitmaps
  4864. - * @param nnew[out]   Memory size, in bytes, of the bitmaps that were locked since the last frame
  4865. - *
  4866. - * @note This is a debug function, and is undefined within release builds
  4867. - */
  4868. +//Loads either animation (bm_load_animation) or still image (bm_load)
  4869. +extern int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, int *keyframe = NULL, int can_drop_frames = 0, int dir_type = CF_TYPE_ANY);
  4870. +
  4871. +// This locks down a bitmap and returns a pointer to a bitmap
  4872. +// that can be accessed until you call bm_unlock.   Only lock
  4873. +// a bitmap when you need it!  This will convert it into the
  4874. +// appropriate format also.
  4875. +extern bitmap * bm_lock(int bitmapnum, ubyte bpp, ubyte flags, bool nodebug = false);
  4876. +
  4877. +//gets the image type
  4878. +ubyte bm_get_type(int handle);
  4879. +
  4880. +// Unlocks a bitmap
  4881. +extern void bm_unlock(int bitmapnum);
  4882. +
  4883. +//WMC - Returns 0 if invalid, nonzero if valid
  4884. +extern int bm_is_valid(int handle);
  4885. +
  4886. +// Gets info.   w,h,or flags,nframes or fps can be NULL if you don't care.
  4887. +//WMC - Returns -1 on failure, handle or first frame handle on success.
  4888. +int bm_get_info(int bitmapnum, int *w = NULL, int * h = NULL, ubyte * flags = NULL, int *nframes = NULL, int *fps = NULL);
  4889. +
  4890. +// get filename
  4891. +extern void bm_get_filename(int bitmapnum, char *filename);
  4892. +
  4893. +// call to load all data for all bitmaps that have been requested to be loaded
  4894. +extern void bm_gfx_load_all();
  4895. +extern void bm_unload_all();
  4896. +
  4897. +// Returns number of bytes of bitmaps locked this frame
  4898. +// ntotal = number of bytes of bitmaps locked this frame
  4899. +// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
  4900.  void bm_get_frame_usage(int *ntotal, int *nnew);
  4901.  
  4902. -/**
  4903. - * @brief Reloads an existing bmpman slot with different bitmap
  4904. - *
  4905. - * @param[in] filename The filename of the image to load
  4906. - *
  4907. - * @returns The bitmap handle on success, or
  4908. - * @returns A negative value on failure
  4909. - *
  4910. - * @note This should only be used if you are certain the new picture is the same type, has same dimensions, etc.
  4911. - */
  4912. +// Reload a different image into an existing bmpman slot
  4913.  int bm_reload(int bitmap_handle, const char* filename);
  4914.  
  4915. -/**
  4916. - * @brief Tells bmpman to start keeping track of what bitmaps are used where
  4917. - */
  4918. -void bm_page_in_start();
  4919. +/*
  4920. +* Example on using bm_create
  4921. +*
  4922. +{
  4923. +static int test_inited = 0;
  4924. +static int test_bmp;
  4925. +static uint test_bmp_data[128*64];
  4926. +
  4927. +if ( !test_inited )    {
  4928. +test_inited = 1;
  4929. +// Create the new bitmap and fill in its data.
  4930. +// When you're done with it completely, call
  4931. +// bm_release to free up the bitmap handle
  4932. +test_bmp = bm_create( 32, 128, 64, test_bmp_data );
  4933. +int i,j;
  4934. +for (i=0; i<64; i++ )  {
  4935. +for (j=0; j<64; j++ )  {
  4936. +uint r=i*4;
  4937. +test_bmp_data[j+i*128] = r;
  4938. +}
  4939. +}
  4940. +}
  4941. +
  4942. +bm_unload(test_bmp);   // this pages out the data, so that the
  4943. +// next bm_lock will convert the new data to the
  4944. +// correct bpp
  4945. +
  4946. +// put in new data
  4947. +int x,y;
  4948. +gr_reset_clip();
  4949. +for (y=0; y<64; y++)
  4950. +for (x=0; x<128; x++ )
  4951. +test_bmp_data[y*128+x] = 15;
  4952. +
  4953. +// Draw the bitmap to upper left corner
  4954. +gr_set_bitmap(test_bmp);
  4955. +gr_bitmap( 0,0 );
  4956. +}
  4957. +*/
  4958. +
  4959. +
  4960. +//============================================================================
  4961. +// Paging stuff
  4962. +//============================================================================
  4963.  
  4964. -/**
  4965. - * @brief Tells bmpman to stop paging (?)
  4966. - */
  4967. +void bm_page_in_start();
  4968.  void bm_page_in_stop();
  4969.  
  4970.  // Paging code in a library should call these functions
  4971.  // in its page in function.
  4972.  
  4973. -/**
  4974. - * @brief Marks a texture as being used for this level
  4975. - *
  4976. - * @param[in] num_frames If specified, assumes this is an animated texture
  4977. - */
  4978. +// Marks a texture as being used for this level
  4979. +// If num_frames is passed, assume this is an animation
  4980.  void bm_page_in_texture(int bitmapnum, int num_frames = 0);
  4981.  
  4982. -/**
  4983. - * @brief Marks a textures as being used for level and is transparant
  4984. - *
  4985. - * @param[in] num_frames If specified, assumes this is an animated texture
  4986. - */
  4987. +// marks a texture as being a transparent textyre used for this level
  4988. +// Marks a texture as being used for this level
  4989. +// If num_frames is passed, assume this is an animation
  4990.  void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
  4991.  
  4992. -/**
  4993. - * @brief Marks a texture as being used for this level, and is anti-aliased
  4994. - *
  4995. - * @param[in] num_frames If specified, assumes this is an animated texture
  4996. - */
  4997. +// Marks an aabitmap as being used for this level
  4998. +// If num_frames is passed, assume this is an animation
  4999.  void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
  5000.  
  5001. -/**
  5002. - * @brief Unloads the bitmap indexed by handle that was previously paged-in
  5003. - *
  5004. - * @returns 0 If the bitmap had already been released, or
  5005. - * @returns 0 If the handle is invalid, or
  5006. - * @returns 1 If successful
  5007. - */
  5008. -bool bm_page_out(int handle);
  5009. -
  5010. -/**
  5011. - * @brief Sets BMPMAN's memory mode
  5012. - *
  5013. - * @details 0 = High memory;
  5014. - *          1 = Low memory (loads every other frame of ani's);
  5015. - *          2 = Debug low memory (only use first frame of each ani)
  5016. - *
  5017. - * @todo This should use an enum, or instead allow an arbitrary number to drop frames (like 1/2, 1/3, etc.)
  5018. - */
  5019. +// unload a texture that was paged in
  5020. +int bm_page_out(int handle);
  5021. +
  5022. +//
  5023. +// Mode: 0 = High memory
  5024. +//       1 = Low memory ( every other frame of ani's)
  5025. +//       2 = Debug low memory ( only use first frame of each ani )
  5026.  void bm_set_low_mem(int mode);
  5027.  
  5028. -/**
  5029. - * @brief Sets bm_set_components and bm_get_components to reference screen format functions
  5030. - */
  5031. -void BM_SELECT_SCREEN_FORMAT();
  5032. +const char *bm_get_filename(int handle);
  5033.  
  5034. -/**
  5035. - * @brief Sets bm_set_components and bm_get_components to reference texture format functions
  5036. - */
  5037. +void BM_SELECT_SCREEN_FORMAT();
  5038.  void BM_SELECT_TEX_FORMAT();
  5039. -
  5040. -/**
  5041. - * @brief Sets bm_set_components and bm_get_components to reference texture format functions (with alpha)
  5042. - */
  5043.  void BM_SELECT_ALPHA_TEX_FORMAT();
  5044.  
  5045. -/**
  5046. - * @brief Functional pointer that references any of the bm_set_components functions.
  5047. - *
  5048. - * @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
  5049. - * format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
  5050. - *
  5051. - * @param[out] pixel The pixel to set
  5052. - * @param[in] r Red value   (may not be NULL)
  5053. - * @param[in] g Green value (may not be NULL)
  5054. - * @param[in] b Blue value  (may not be NULL)
  5055. - * @param[in] a Alpha value (currently ignored)
  5056. - *
  5057. - * @note z64 - These functions were made predating the introduction of C++ classes, and are basically the equivalent
  5058. - * of Pixel::set(ubyte *r, ubyte *b, ubyte *g). The original comment mentions that any of the rgba params may be
  5059. - * NULL, but this is by far _NOT_ the case, as a NULL value will cause undefined behavior (really really bad chroma
  5060. - * corruption)
  5061. - *
  5062. - * @note These functions assume the incoming bitdepth will always be >= to the outgoing bitdepth of the pixel. Should
  5063. - * the incoming bitdepth be lower, the outgoing values will appear darker than they should be
  5064. - */
  5065. +// set the rgba components of a pixel, any of the parameters can be NULL
  5066.  extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5067. -
  5068. -/**
  5069. - * @brief Functional pointer that references any of the bm_set_components_32 functions.
  5070. - *
  5071. - * @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
  5072. - * format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
  5073. - *
  5074. - * @see bm_set_components
  5075. - */
  5076.  extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5077. +void bm_set_components_argb_d3d_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5078. +void bm_set_components_argb_d3d_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5079. +void bm_set_components_argb_d3d_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5080. +void bm_set_components_argb_d3d_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5081.  
  5082. -/**
  5083. - * @brief Sets the 16bpp screen pixel to the specified RGBA value
  5084. - *
  5085. - * @see bm_set_components
  5086. - */
  5087. -void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5088. -
  5089. -/**
  5090. - * @brief Sets the 32bpp screen pixel to the specified RGBA value
  5091. - *
  5092. - * @see bm_set_components
  5093. - */
  5094. -void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5095. -
  5096. -/**
  5097. - * @brief Sets the 16bpp texture pixel to the specified RGBA value
  5098. - *
  5099. - * @see bm_set_components
  5100. - */
  5101. -void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5102. -
  5103. -/**
  5104. - * @brief Sets the 32bpp texture pixel to the specified RGBA value
  5105. - *
  5106. - * @see bm_set_components
  5107. - */
  5108. -void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5109. -
  5110. -/**
  5111. - * @brief Gets the RGBA components of a pixel according to the selected mode
  5112. - *
  5113. - * @see BM_SELECT_SCREEN_FORMAT() BM_SELECT_TEX_FORMAT() BM_SELECT_ALPHA_TEX_FORMAT()
  5114. - */
  5115. +// get the rgba components of a pixel, any of the parameters can be NULL
  5116.  void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
  5117.  
  5118. -/**
  5119. - * @brief Returns the compression type of the bitmap indexed by handle
  5120. - */
  5121. -int bm_is_compressed(int handle);
  5122. -
  5123. -/**
  5124. - * @brief Gets the correct TCACHE_TYPE for compressed graphics (uncompressed are assumed TCACHE_TYPE_NORMAL)
  5125. - */
  5126. -int bm_get_tcache_type(int handle);
  5127. -
  5128. -/**
  5129. - * @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
  5130. - */
  5131. -size_t bm_get_size(int handle);
  5132. -
  5133. -/**
  5134. - * @brief Gets the number of mipmaps of the indexed texture
  5135. - */
  5136. -int bm_get_num_mipmaps(int handle);
  5137. -
  5138. -/**
  5139. - * @brief Checks to see if the indexed bitmap has an alpha channel
  5140. - *
  5141. - * @note Currently just checks if the bitmap is 32bpp and is not a .PCX
  5142. - */
  5143. -bool bm_has_alpha_channel(int handle);
  5144. -
  5145. -/**
  5146. - * @brief (DEBUG) Prints all loaded bitmaps to an outwindow
  5147. - */
  5148. +extern int GLOWMAP;    //this holds a reference to a map that is a fully lit version of its index -Bobboau
  5149. +extern int SPECMAP;    //this holds a reference to a map that is for specular mapping -Bobboau
  5150. +extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
  5151. +extern int NORMMAP;    // normal mapping
  5152. +extern int HEIGHTMAP;  // height map for normal mapping
  5153. +extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
  5154. +
  5155. +int bm_is_compressed(int num);
  5156. +int bm_get_tcache_type(int num);
  5157. +int bm_get_size(int num);
  5158. +int bm_get_num_mipmaps(int num);
  5159. +int bm_has_alpha_channel(int handle);
  5160. +
  5161.  void bm_print_bitmaps();
  5162.  
  5163. -/**
  5164. - * @brief Creates a render target as close to the desired resolution as possible.
  5165. - *
  5166. - * @returns the handle of an avilable render target if successful, or
  5167. - * @returns -1 if not successful
  5168. - *
  5169. - * @note BM_FLAG_RENDER_TARGET_STATIC are drawn once/infrequently, while BM_FLAG_RENDER_TARGET_DYNAMIC are drawn roughly once every frame
  5170. - */
  5171.  int bm_make_render_target(int width, int height, int flags);
  5172. +int bm_is_render_target(int bitmap_id);
  5173. +int bm_set_render_target(int handle, int face = -1);
  5174.  
  5175. -/**
  5176. - * @brief Checks to see if the given bitmap indexed by handle is a render target
  5177. - *
  5178. - * @returns The render type (BM_TYPE) if it is a render target, or
  5179. - * @returns 0 if it is not
  5180. - */
  5181. -int bm_is_render_target(int handle);
  5182. -
  5183. -/**
  5184. - * @brief (GR function) Calls gr_bm_set_render target for the given bitmap indexed by handle
  5185. - *
  5186. - * @returns true if successful, or
  5187. - * @returns false if unsuccessful
  5188. - */
  5189. -bool bm_set_render_target(int handle, int face = -1);
  5190. -
  5191. -/**
  5192. - * @brief Loads and parses an .EFF
  5193. - *
  5194. - * @param[in]  filename The filename of the .EFF
  5195. - * @param[in]  dir_type
  5196. - * @param[out] nframes (optional) If given, is set to the number of frames this .EFF has
  5197. - * @param[out] nfps    (optional) If given, is set to the fps of this .EFF
  5198. - * @param[out] key     (optional) If given, is set to the keyframe index of this .EFF
  5199. - * @param[out] type    (optional) If given, is set to the BM_TYPE of the .EFF
  5200. - *
  5201. - * @returns true If successful
  5202. - * @returns false If not successful
  5203. - */
  5204. -bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type);
  5205. -
  5206. -#endif
  5207. +int bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type);
  5208. +#endif
  5209. \ No newline at end of file
  5210. --
  5211. 1.9.5.msysgit.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement