mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 17:46:53 -10:00
1374 lines
34 KiB
C++
1374 lines
34 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
// D3D8 includes
|
|
#include <d3d8.h>
|
|
#include <d3dx8.h>
|
|
|
|
#include <ctype.h>
|
|
#include "globalincs/pstypes.h"
|
|
#include "pcxutils/pcxutils.h"
|
|
#include "bmpman/bmpman.h"
|
|
#include "palman/palman.h"
|
|
#include "graphics/2d.h"
|
|
#include "anim/animplay.h"
|
|
#include "io/timer.h"
|
|
#include "globalincs/systemvars.h"
|
|
#include "io/key.h"
|
|
#include "anim/packunpack.h"
|
|
#include "graphics/grinternal.h"
|
|
#include "graphics/grd3dinternal.h"
|
|
#include "ship/ship.h"
|
|
#include "debugconsole/dbugfile.h"
|
|
#include "bmpman/bmpman.h"
|
|
#include "Cmdline/cmdline.h"
|
|
#include "cfile/cfile.h"
|
|
|
|
#include "graphics/grd3dbmpman.h"
|
|
|
|
extern bitmap_entry bm_bitmaps[];
|
|
|
|
D3DBitmapData d3d_bitmap_entry[MAX_BITMAPS];
|
|
|
|
// keep this defined to use per-ship nondarkening pixels
|
|
#define BMPMAN_SPECIAL_NONDARK
|
|
|
|
int bm_d3d_inited = 0;
|
|
int bm_d3d_next_handle = 1;
|
|
|
|
// 16 bit pixel formats
|
|
//extern int Bm_pixel_format;
|
|
|
|
int bm_d3d_get_next_handle()
|
|
{
|
|
int n = bm_d3d_next_handle;
|
|
bm_d3d_next_handle++;
|
|
if ( bm_d3d_next_handle > 30000 ) {
|
|
bm_d3d_next_handle = 1;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
// Frees a bitmaps data if it should, and
|
|
// Returns true if bitmap n can free it's data.
|
|
static void bm_d3d_free_data(int n)
|
|
{
|
|
bitmap_entry *be;
|
|
bitmap *bmp;
|
|
|
|
Assert( n >= 0 && n < MAX_BITMAPS );
|
|
|
|
be = &bm_bitmaps[n];
|
|
bmp = &be->bm;
|
|
|
|
if(d3d_bitmap_entry[n].tinterface != NULL) {
|
|
d3d_bitmap_entry[n].tinterface->Release();
|
|
d3d_bitmap_entry[n].tinterface = NULL;
|
|
}
|
|
|
|
// If there isn't a bitmap in this structure, don't
|
|
// do anything but clear out the bitmap info
|
|
if ( be->type==BM_TYPE_NONE)
|
|
goto SkipFree;
|
|
|
|
// If this bitmap doesn't have any data to free, skip
|
|
// the freeing it part of this.
|
|
if ( bmp->data == 0 )
|
|
goto SkipFree;
|
|
|
|
// Don't free up memory for user defined bitmaps, since
|
|
// BmpMan isn't the one in charge of allocating/deallocing them.
|
|
if ( ( be->type==BM_TYPE_USER ) )
|
|
goto SkipFree;
|
|
|
|
// Free up the data now!
|
|
|
|
// mprintf(( "Bitmap %d freed %d bytes\n", n, bm_bitmaps[n].data_size ));
|
|
if(bmp->data != NULL) {
|
|
free((void *)bmp->data);
|
|
}
|
|
|
|
SkipFree:
|
|
|
|
// Clear out & reset the bitmap data structure
|
|
bmp->flags = 0;
|
|
bmp->bpp = 0;
|
|
bmp->data = 0;
|
|
bmp->palette = NULL;
|
|
}
|
|
|
|
static void *bm_d3d_malloc( int n, int size )
|
|
{
|
|
Assert( n >= 0 && n < MAX_BITMAPS );
|
|
// mprintf(( "Bitmap %d allocated %d bytes\n", n, size ));
|
|
return malloc(size);
|
|
}
|
|
|
|
void bm_d3d_close()
|
|
{
|
|
if ( bm_d3d_inited ) {
|
|
for (int i=0; i<MAX_BITMAPS; i++ ) {
|
|
bm_d3d_free_data(i); // clears flags, bbp, data, etc
|
|
}
|
|
bm_d3d_inited = 0;
|
|
}
|
|
}
|
|
|
|
void bm_d3d_init()
|
|
{
|
|
if (!bm_d3d_inited) {
|
|
bm_d3d_inited = 1;
|
|
atexit(bm_d3d_close);
|
|
}
|
|
|
|
for (int i = 0; i < MAX_BITMAPS; i++ ) {
|
|
bm_bitmaps[i].filename[0] = '\0';
|
|
bm_bitmaps[i].type = BM_TYPE_NONE;
|
|
bm_bitmaps[i].info.user.data = NULL;
|
|
bm_bitmaps[i].bm.data = 0;
|
|
bm_bitmaps[i].bm.palette = NULL;
|
|
|
|
d3d_bitmap_entry[i].tinterface = NULL;
|
|
|
|
bm_d3d_free_data(i); // clears flags, bbp, data, etc
|
|
}
|
|
}
|
|
|
|
void bm_d3d_get_frame_usage(int *ntotal, int *nnew)
|
|
{
|
|
}
|
|
|
|
// Creates a bitmap that exists in RAM somewhere, instead
|
|
// of coming from a disk file. You pass in a pointer to a
|
|
// block of 32 (or 8)-bit-per-pixel data. Right now, the only
|
|
// bpp you can pass in is 32 or 8. On success, it returns the
|
|
// bitmap number. You cannot free that RAM until bm_release
|
|
// is called on that bitmap.
|
|
int bm_d3d_create( int bpp, int w, int h, void * data, int flags )
|
|
{
|
|
|
|
Assert(bm_d3d_inited);
|
|
|
|
int i, n, first_slot = MAX_BITMAPS;
|
|
|
|
if(bpp == 8){
|
|
Assert(flags & BMP_AABITMAP);
|
|
} else {
|
|
Assert(bpp == 16);
|
|
}
|
|
|
|
for (i = MAX_BITMAPS-1; i >= 0; i-- ) {
|
|
if ( bm_bitmaps[i].type == BM_TYPE_NONE ) {
|
|
first_slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert(d3d_bitmap_entry[i].tinterface == NULL);
|
|
|
|
|
|
n = first_slot;
|
|
Assert( n > -1 );
|
|
|
|
// Out of bitmap slots
|
|
if ( n == -1 ) return -1;
|
|
|
|
memset( &bm_bitmaps[n], 0, sizeof(bitmap_entry) );
|
|
|
|
sprintf( bm_bitmaps[n].filename, "TMP%dx%d", w, h );
|
|
bm_bitmaps[n].type = BM_TYPE_USER;
|
|
bm_bitmaps[n].palette_checksum = 0;
|
|
|
|
bm_bitmaps[n].bm.w = (short) w;
|
|
bm_bitmaps[n].bm.h = (short) h;
|
|
bm_bitmaps[n].bm.rowsize = (short) w;
|
|
bm_bitmaps[n].bm.bpp = (unsigned char) bpp;
|
|
bm_bitmaps[n].bm.flags = 0;
|
|
bm_bitmaps[n].bm.flags |= flags;
|
|
bm_bitmaps[n].bm.data = 0;
|
|
bm_bitmaps[n].bm.palette = NULL;
|
|
|
|
bm_bitmaps[n].info.user.bpp = ubyte(bpp);
|
|
bm_bitmaps[n].info.user.data = data;
|
|
bm_bitmaps[n].info.user.flags = ubyte(flags);
|
|
|
|
bm_bitmaps[n].handle = bm_get_next_handle()*MAX_BITMAPS + n;
|
|
bm_bitmaps[n].last_used = -1;
|
|
|
|
d3d_bitmap_entry[n].tinterface = NULL;
|
|
|
|
return bm_bitmaps[n].handle;
|
|
}
|
|
|
|
// sub helper function. Given a raw filename and an extension, try and find the bitmap
|
|
// returns -1 if it could not be found
|
|
// 0 if it was found as a file
|
|
// 1 if it already exists, fills in handle
|
|
int Bm_d3d_ignore_duplicates = 0;
|
|
int bm_d3d_load_sub(char *real_filename, const char *ext, int *handle)
|
|
{
|
|
int i;
|
|
char filename[MAX_FILENAME_LEN] = "";
|
|
|
|
strcpy( filename, real_filename );
|
|
strcat( filename, ext );
|
|
for (i=0; i<(int)strlen(filename); i++ ){
|
|
filename[i] = char(tolower(filename[i]));
|
|
}
|
|
|
|
// try to find given filename to see if it has been loaded before
|
|
if(!Bm_d3d_ignore_duplicates){
|
|
for (i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( (bm_bitmaps[i].type != BM_TYPE_NONE) && !stricmp(filename, bm_bitmaps[i].filename) ) {
|
|
nprintf (("BmpMan", "Found bitmap %s -- number %d\n", filename, i));
|
|
*handle = bm_bitmaps[i].handle;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// try and find the file
|
|
CFILE *test = cfopen(filename, "rb");
|
|
if(test != NULL){
|
|
cfclose(test);
|
|
return 0;
|
|
}
|
|
|
|
// could not be found
|
|
return -1;
|
|
}
|
|
|
|
// This loads a bitmap so we can draw with it later.
|
|
// It returns a negative number if it couldn't load
|
|
// the bitmap. On success, it returns the bitmap
|
|
// number. Function doesn't acutally load the data, only
|
|
// width, height, and possibly flags.
|
|
int bm_d3d_load( char * real_filename )
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
int i, n;
|
|
int w, h;
|
|
char filename[MAX_FILENAME_LEN];
|
|
|
|
// nice little trick for keeping standalone memory usage way low - always return a bogus bitmap
|
|
if(Game_mode & GM_STANDALONE_SERVER){
|
|
strcpy(filename,"test128");
|
|
}
|
|
|
|
// make sure no one passed an extension
|
|
strcpy( filename, real_filename );
|
|
char *p = strchr( filename, '.' );
|
|
if ( p ) {
|
|
mprintf(( "Someone passed an extension to bm_load for file '%s'\n", real_filename ));
|
|
//Int3();
|
|
*p = 0;
|
|
}
|
|
|
|
// Lets find out what type it is
|
|
int type = BM_TYPE_NONE;
|
|
{
|
|
bool found = false;
|
|
|
|
//int handle = -1;
|
|
const int NUM_TYPES = 4;
|
|
const int type_list[NUM_TYPES] = {BM_TYPE_TGA, BM_TYPE_JPG, BM_TYPE_DDS, BM_TYPE_PCX};
|
|
const char *ext_list[NUM_TYPES] = {".tga", ".jpg", ".dds", ".pcx"};
|
|
|
|
// Only load TGA and JPG if given flag, support DDS and PCX by default
|
|
int i = Cmdline_jpgtga ? 0 : 2; // 2 Means start with DDS and fall back to PCX
|
|
|
|
for(; i < NUM_TYPES; i++) {
|
|
|
|
int handle = 0;
|
|
int result = bm_d3d_load_sub(filename, ext_list[i], &handle);
|
|
|
|
// Image is already loaded
|
|
if(result == 1) {
|
|
return handle;
|
|
}
|
|
|
|
// File was found
|
|
if(result == 0) {
|
|
strcat(filename, ext_list[i]);
|
|
type = type_list[i];
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// No match was found
|
|
if(found == false) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
Assert(type != BM_TYPE_NONE);
|
|
|
|
// Find an open slot
|
|
int first_slot = MAX_BITMAPS;
|
|
for (i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( (bm_bitmaps[i].type == BM_TYPE_NONE) ){
|
|
first_slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert(d3d_bitmap_entry[i].tinterface == NULL);
|
|
|
|
n = first_slot;
|
|
Assert( n < MAX_BITMAPS );
|
|
|
|
if ( n == MAX_BITMAPS ) return -1;
|
|
|
|
|
|
if(type == BM_TYPE_PCX) {
|
|
int pcx_error=pcx_read_header( filename, &w, &h, NULL );
|
|
if ( pcx_error != PCX_ERROR_NONE ) {
|
|
DBUGFILE_OUTPUT_1("bm_pcx: Cant load %s",filename);
|
|
mprintf(( "bm_pcx: Couldn't open '%s'\n", filename ));
|
|
return -1;
|
|
}
|
|
} else {
|
|
// Let D3DX handle this
|
|
if(d3d_read_header_d3dx( filename, type, &w, &h) == false) {
|
|
DBUGFILE_OUTPUT_1("not bm_pcx: Cant load %s",filename);
|
|
mprintf(( "not bm_pcx: Couldn't open '%s'\n", filename ));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// ensure fields are cleared out from previous bitmap
|
|
memset( &bm_bitmaps[n], 0, sizeof(bitmap_entry) );
|
|
|
|
// Mark the slot as filled, because cf_read might load a new bitmap
|
|
// into this slot.
|
|
bm_bitmaps[n].type = (ubyte) type;
|
|
Assert ( strlen(filename) < MAX_FILENAME_LEN );
|
|
strncpy(bm_bitmaps[n].filename, filename, MAX_FILENAME_LEN-1 );
|
|
bm_bitmaps[n].bm.w = short(w);
|
|
bm_bitmaps[n].bm.rowsize = short(w);
|
|
bm_bitmaps[n].bm.h = short(h);
|
|
bm_bitmaps[n].bm.bpp = 0;
|
|
bm_bitmaps[n].bm.flags = 0;
|
|
bm_bitmaps[n].bm.data = 0;
|
|
bm_bitmaps[n].bm.palette = NULL;
|
|
|
|
bm_bitmaps[n].palette_checksum = 0;
|
|
bm_bitmaps[n].handle = bm_get_next_handle()*MAX_BITMAPS + n;
|
|
bm_bitmaps[n].last_used = -1;
|
|
|
|
d3d_bitmap_entry[n].tinterface = NULL;
|
|
|
|
return bm_bitmaps[n].handle;
|
|
}
|
|
|
|
// special load function. basically allows you to load a bitmap which already exists (by filename).
|
|
// this is useful because in some cases we need to have a bitmap which is locked in screen format
|
|
// _and_ texture format, such as pilot pics and squad logos
|
|
int bm_d3d_load_duplicate(char *filename)
|
|
{
|
|
int ret;
|
|
|
|
// ignore duplicates
|
|
Bm_d3d_ignore_duplicates = 1;
|
|
|
|
// load
|
|
ret = bm_load(filename);
|
|
|
|
// back to normal
|
|
Bm_d3d_ignore_duplicates = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int find_block_of(int n)
|
|
{
|
|
int i, cnt, nstart;
|
|
|
|
cnt=0;
|
|
nstart = 0;
|
|
for (i=0; i<MAX_BITMAPS; i++ ) {
|
|
if ( bm_bitmaps[i].type == BM_TYPE_NONE ) {
|
|
if (cnt==0) nstart = i;
|
|
cnt++;
|
|
} else
|
|
cnt=0;
|
|
if ( cnt == n ) return nstart;
|
|
}
|
|
|
|
// Error( LOCATION, "Couldn't find block of %d frames\n", n );
|
|
return -1;
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// bm_load_animation()
|
|
//
|
|
// input: filename => filename of animation
|
|
// nframes => OUTPUT parameter: number of frames in the animation
|
|
// fps => OUTPUT/OPTIONAL parameter: intended fps for the animation
|
|
//
|
|
// returns: bitmap number of first frame in the animation
|
|
//
|
|
int bm_d3d_load_animation( char *real_filename, int *nframes, int *fps, int can_drop_frames, int dir_type)
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
int i, n;
|
|
anim the_anim;
|
|
CFILE *fp;
|
|
char filename[MAX_FILENAME_LEN];
|
|
|
|
strcpy( filename, real_filename );
|
|
char *p = strchr( filename, '.' );
|
|
if ( p ) {
|
|
mprintf(( "Someone passed an extension to bm_load_animation for file '%s'\n", real_filename ));
|
|
//Int3();
|
|
*p = 0;
|
|
}
|
|
strcat( filename, ".ani" );
|
|
|
|
if ( (fp = cfopen(filename, "rb", CFILE_NORMAL, dir_type)) == NULL ) {
|
|
return -1;
|
|
}
|
|
|
|
int reduced = 0;
|
|
#ifndef NDEBUG
|
|
// for debug of ANI sizes
|
|
strcpy(the_anim.name, real_filename);
|
|
#endif
|
|
anim_read_header(&the_anim, fp);
|
|
cfclose(fp);
|
|
|
|
*nframes = the_anim.total_frames;
|
|
if ( fps != NULL ) {
|
|
if ( reduced ) {
|
|
*fps = the_anim.fps / 2;
|
|
} else {
|
|
*fps = the_anim.fps;
|
|
}
|
|
}
|
|
|
|
// first check to see if this ani already has it's frames loaded
|
|
for (i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( (bm_bitmaps[i].type == BM_TYPE_ANI) && !stricmp(filename, bm_bitmaps[i].filename) ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( i < MAX_BITMAPS ) {
|
|
Assert(bm_bitmaps[i].info.ani.num_frames == *nframes);
|
|
return bm_bitmaps[i].handle;
|
|
}
|
|
|
|
n = find_block_of(*nframes);
|
|
if(n < 0){
|
|
return -1;
|
|
}
|
|
|
|
int first_handle = bm_get_next_handle();
|
|
|
|
Assert ( strlen(filename) < MAX_FILENAME_LEN );
|
|
for ( i = 0; i < *nframes; i++ ) {
|
|
memset( &bm_bitmaps[n+i], 0, sizeof(bitmap_entry) );
|
|
bm_bitmaps[n+i].info.ani.first_frame = n;
|
|
bm_bitmaps[n+i].info.ani.num_frames = ubyte(the_anim.total_frames);
|
|
bm_bitmaps[n+i].info.ani.fps = ubyte(the_anim.fps);
|
|
bm_bitmaps[n+i].bm.w = short(the_anim.width);
|
|
bm_bitmaps[n+i].bm.rowsize = short(the_anim.width);
|
|
bm_bitmaps[n+i].bm.h = short(the_anim.height);
|
|
if ( reduced ) {
|
|
bm_bitmaps[n+i].bm.w /= 2;
|
|
bm_bitmaps[n+i].bm.rowsize /= 2;
|
|
bm_bitmaps[n+i].bm.h /= 2;
|
|
}
|
|
bm_bitmaps[n+i].bm.flags = 0;
|
|
bm_bitmaps[n+i].bm.bpp = 0;
|
|
bm_bitmaps[n+i].bm.data = 0;
|
|
bm_bitmaps[n+i].bm.palette = NULL;
|
|
bm_bitmaps[n+i].type = BM_TYPE_ANI;
|
|
bm_bitmaps[n+i].palette_checksum = 0;
|
|
bm_bitmaps[n+i].handle = first_handle*MAX_BITMAPS + n+i;
|
|
bm_bitmaps[n+i].last_used = -1;
|
|
|
|
if ( i == 0 ) {
|
|
sprintf( bm_bitmaps[n+i].filename, "%s", filename );
|
|
} else {
|
|
sprintf( bm_bitmaps[n+i].filename, "%s[%d]", filename, i );
|
|
}
|
|
}
|
|
|
|
return bm_bitmaps[n].handle;
|
|
}
|
|
|
|
// Gets info. w,h,or flags,nframes or fps can be NULL if you don't care.
|
|
void bm_d3d_get_info( int handle, int *w, int * h, ubyte * flags, int *nframes, int *fps, bitmap_section_info **sections )
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
bitmap * bmp;
|
|
if (sections != NULL) *sections = NULL;
|
|
|
|
int bitmapnum = handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE!
|
|
|
|
if ( (bm_bitmaps[bitmapnum].type == BM_TYPE_NONE) || (bm_bitmaps[bitmapnum].handle != handle) ) {
|
|
if (w) *w = 0;
|
|
if (h) *h = 0;
|
|
if (flags) *flags = 0;
|
|
if (nframes) *nframes=0;
|
|
if (fps) *fps=0;
|
|
return;
|
|
}
|
|
|
|
bmp = &(bm_bitmaps[bitmapnum].bm);
|
|
|
|
if (w) *w = bmp->w;
|
|
if (h) *h = bmp->h;
|
|
if (flags) *flags = bmp->flags;
|
|
if ( bm_bitmaps[bitmapnum].type == BM_TYPE_ANI ) {
|
|
if (nframes) {
|
|
*nframes = bm_bitmaps[bitmapnum].info.ani.num_frames;
|
|
}
|
|
if (fps) {
|
|
*fps= bm_bitmaps[bitmapnum].info.ani.fps;
|
|
}
|
|
} else {
|
|
if (nframes) {
|
|
*nframes = 1;
|
|
}
|
|
if (fps) {
|
|
*fps= 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint bm_d3d_get_signature( int handle )
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
int bitmapnum = handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
return bm_bitmaps[bitmapnum].signature;
|
|
}
|
|
|
|
static void bm_d3d_convert_format( int bitmapnum, bitmap *bmp, ubyte bpp, ubyte flags )
|
|
{
|
|
int idx;
|
|
|
|
if(flags & BMP_AABITMAP){
|
|
// Assert(bmp->bpp == 8);
|
|
} else {
|
|
Assert(bmp->bpp == 16);
|
|
}
|
|
|
|
// maybe swizzle to be an xparent texture
|
|
if(!(bmp->flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_XPARENT)) {
|
|
for(idx=0; idx<bmp->w*bmp->h; idx++){
|
|
|
|
// if the pixel is transparent
|
|
if ( ((ushort*)bmp->data)[idx] == Gr_t_green.mask) {
|
|
((ushort*)bmp->data)[idx] = 0;
|
|
}
|
|
}
|
|
|
|
bmp->flags |= BMP_TEX_XPARENT;
|
|
}
|
|
}
|
|
|
|
void bm_d3d_lock_pcx( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
|
|
{
|
|
ubyte *data, *palette;
|
|
ubyte pal[768];
|
|
palette = NULL;
|
|
|
|
// Unload any existing data
|
|
bm_d3d_free_data( bitmapnum );
|
|
|
|
// allocate bitmap data
|
|
if(bpp == 16 && Cmdline_pcx32) {
|
|
bpp = 32;
|
|
}
|
|
|
|
data = (ubyte *)bm_d3d_malloc(bitmapnum, bmp->w * bmp->h * (bpp / 8));
|
|
bmp->data = (uint)data;
|
|
memset( data, 0, bmp->w * bmp->h * (bpp / 8));
|
|
|
|
bmp->bpp = bpp;
|
|
|
|
if(bpp == 8){
|
|
palette = pal;
|
|
bmp->palette = gr_palette;
|
|
} else {
|
|
bmp->palette = NULL;
|
|
}
|
|
|
|
Assert( &be->bm == bmp );
|
|
|
|
// some sanity checks on flags
|
|
Assert(!((flags & BMP_AABITMAP) && (flags & BMP_TEX_ANY))); // no aabitmap textures
|
|
Assert(!((flags & BMP_TEX_XPARENT) && (flags & BMP_TEX_NONDARK))); // can't be a transparent texture and a nondarkening texture
|
|
|
|
if(bpp == 8){
|
|
int pcx_error=pcx_read_bitmap_8bpp( be->filename, data, palette );
|
|
if ( pcx_error != PCX_ERROR_NONE ) {
|
|
//return -1;
|
|
}
|
|
} else {
|
|
int pcx_error;
|
|
|
|
if(bpp == 16){
|
|
|
|
// load types
|
|
Assert(!(flags & BMP_AABITMAP));
|
|
Assert(!(flags & BMP_TEX_NONDARK));
|
|
|
|
pcx_error = pcx_read_bitmap_16bpp( be->filename, data );
|
|
|
|
bm_d3d_convert_format( bitmapnum, bmp, bpp, flags );
|
|
|
|
} else {
|
|
pcx_error = pcx_read_bitmap_32( be->filename, data );
|
|
}
|
|
|
|
Assert(pcx_error == PCX_ERROR_NONE );
|
|
}
|
|
}
|
|
|
|
void bm_d3d_lock_ani( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
|
|
{
|
|
anim *the_anim;
|
|
anim_instance *the_anim_instance;
|
|
bitmap *bm;
|
|
ubyte *frame_data;
|
|
int size, i;
|
|
int first_frame, nframes;
|
|
|
|
first_frame = be->info.ani.first_frame;
|
|
nframes = bm_bitmaps[first_frame].info.ani.num_frames;
|
|
|
|
if ( (the_anim = anim_load(bm_bitmaps[first_frame].filename)) == NULL ) {
|
|
// Error(LOCATION, "Error opening %s in bm_lock\n", be->filename);
|
|
}
|
|
|
|
if ( (the_anim_instance = init_anim_instance(the_anim, bpp)) == NULL ) {
|
|
// Error(LOCATION, "Error opening %s in bm_lock\n", be->filename);
|
|
anim_free(the_anim);
|
|
}
|
|
|
|
int can_drop_frames = 0;
|
|
|
|
if ( the_anim->total_frames != bm_bitmaps[first_frame].info.ani.num_frames ) {
|
|
can_drop_frames = 1;
|
|
}
|
|
|
|
bm = &bm_bitmaps[first_frame].bm;
|
|
size = bm->w * bm->h * bpp / 8;
|
|
|
|
for ( i=0; i<nframes; i++ ) {
|
|
be = &bm_bitmaps[first_frame+i];
|
|
bm = &bm_bitmaps[first_frame+i].bm;
|
|
|
|
// Unload any existing data
|
|
bm_d3d_free_data( first_frame+i );
|
|
|
|
bm->flags = 0;
|
|
bm->bpp = bpp;
|
|
bm->data = (uint)bm_d3d_malloc(first_frame + i, size);
|
|
|
|
frame_data = anim_get_next_raw_buffer(the_anim_instance, 0 ,flags & BMP_AABITMAP ? 1 : 0, bm->bpp);
|
|
|
|
if ( frame_data == NULL ) {
|
|
// Error(LOCATION,"Fatal error locking .ani file: %s\n", be->filename);
|
|
}
|
|
|
|
ubyte *dptr, *sptr;
|
|
|
|
sptr = frame_data;
|
|
dptr = (ubyte *)bm->data;
|
|
|
|
if ( (bm->w!=the_anim->width) || (bm->h!=the_anim->height) ) {
|
|
// Scale it down
|
|
// Int3(); // not ready yet - should only be ingame
|
|
|
|
// 8 bit
|
|
if(bpp == 8){
|
|
int w,h;
|
|
fix u, utmp, v, du, dv;
|
|
|
|
u = v = 0;
|
|
|
|
du = ( the_anim->width*F1_0 ) / bm->w;
|
|
dv = ( the_anim->height*F1_0 ) / bm->h;
|
|
|
|
for (h = 0; h < bm->h; h++) {
|
|
ubyte *drow = &dptr[bm->w * h];
|
|
ubyte *srow = &sptr[f2i(v)*the_anim->width];
|
|
|
|
utmp = u;
|
|
|
|
for (w = 0; w < bm->w; w++) {
|
|
*drow++ = srow[f2i(utmp)];
|
|
utmp += du;
|
|
}
|
|
v += dv;
|
|
}
|
|
}
|
|
// 16 bpp
|
|
else {
|
|
int w,h;
|
|
fix u, utmp, v, du, dv;
|
|
|
|
u = v = 0;
|
|
|
|
du = ( the_anim->width*F1_0 ) / bm->w;
|
|
dv = ( the_anim->height*F1_0 ) / bm->h;
|
|
|
|
for (h = 0; h < bm->h; h++) {
|
|
ushort *drow = &((ushort*)dptr)[bm->w * h];
|
|
ushort *srow = &((ushort*)sptr)[f2i(v)*the_anim->width];
|
|
|
|
utmp = u;
|
|
|
|
for (w = 0; w < bm->w; w++) {
|
|
*drow++ = srow[f2i(utmp)];
|
|
utmp += du;
|
|
}
|
|
v += dv;
|
|
}
|
|
}
|
|
} else {
|
|
// 1-to-1 mapping
|
|
memcpy(dptr, sptr, size);
|
|
}
|
|
|
|
bm_d3d_convert_format( first_frame+i, bm, bpp, flags );
|
|
|
|
// Skip a frame
|
|
if ( (i < nframes-1) && can_drop_frames ) {
|
|
frame_data = anim_get_next_raw_buffer(the_anim_instance, 0, flags & BMP_AABITMAP ? 1 : 0, bm->bpp);
|
|
}
|
|
|
|
//mprintf(( "Checksum = %d\n", be->palette_checksum ));
|
|
}
|
|
|
|
free_anim_instance(the_anim_instance);
|
|
anim_free(the_anim);
|
|
}
|
|
|
|
|
|
void bm_d3d_lock_user( int handle, int bitmapnum, bitmap_entry *be, bitmap *bmp, ubyte bpp, ubyte flags )
|
|
{
|
|
// Unload any existing data
|
|
bm_d3d_free_data( bitmapnum );
|
|
|
|
switch( be->info.user.bpp ) {
|
|
case 16: // user 16 bit bitmap
|
|
bmp->bpp = bpp;
|
|
bmp->flags = be->info.user.flags;
|
|
bmp->data = (uint)be->info.user.data;
|
|
break;
|
|
|
|
case 8: // Going from 8 bpp to something (probably only for aabitmaps)
|
|
// Assert(flags & BMP_AABITMAP);
|
|
bmp->bpp = bpp;
|
|
bmp->flags = be->info.user.flags;
|
|
bmp->data = (uint)be->info.user.data;
|
|
break;
|
|
}
|
|
|
|
bm_d3d_convert_format( bitmapnum, bmp, bpp, flags );
|
|
}
|
|
|
|
bool d3d_lock_and_set_internal_texture(int stage, int handle, ubyte bpp, ubyte flags, float *u_scale, float *v_scale )
|
|
{
|
|
int bitmapnum = handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
int valid_type =
|
|
bm_bitmaps[bitmapnum].type == BM_TYPE_TGA ||
|
|
bm_bitmaps[bitmapnum].type == BM_TYPE_DDS ||
|
|
bm_bitmaps[bitmapnum].type == BM_TYPE_JPG;
|
|
|
|
if(valid_type)
|
|
{
|
|
// There is no internal texture
|
|
bm_d3d_lock(handle, bpp, flags );
|
|
bm_unlock(handle);
|
|
|
|
if(u_scale) *u_scale = d3d_bitmap_entry[bitmapnum].uscale;
|
|
if(v_scale) *v_scale = d3d_bitmap_entry[bitmapnum].vscale;
|
|
|
|
d3d_SetTexture(stage, d3d_bitmap_entry[bitmapnum].tinterface);
|
|
return true;
|
|
}
|
|
|
|
if(Cmdline_d3d_lesstmem && bm_bitmaps[bitmapnum].type == BM_TYPE_PCX)
|
|
{
|
|
if(d3d_bitmap_entry[bitmapnum].tinterface == NULL)
|
|
{
|
|
// Trick the normal functions into getting the info we need
|
|
tcache_slot_d3d t;
|
|
t.bitmap_id = -1;
|
|
|
|
d3d_create_texture(handle, flags, &t, 0);
|
|
d3d_bitmap_entry[bitmapnum].uscale = t.u_scale;
|
|
d3d_bitmap_entry[bitmapnum].vscale = t.v_scale;
|
|
d3d_bitmap_entry[bitmapnum].tinterface = t.d3d8_thandle;
|
|
|
|
free((void *) bm_bitmaps[bitmapnum].bm.data);
|
|
bm_bitmaps[bitmapnum].bm.data = NULL;
|
|
}
|
|
|
|
if(u_scale) *u_scale = d3d_bitmap_entry[bitmapnum].uscale;
|
|
if(v_scale) *v_scale = d3d_bitmap_entry[bitmapnum].vscale;
|
|
|
|
d3d_SetTexture(stage, d3d_bitmap_entry[bitmapnum].tinterface);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// This locks down a bitmap and returns a pointer to a bitmap
|
|
// that can be accessed until you call bm_unlock. Only lock
|
|
// a bitmap when you need it! This will convert it into the
|
|
// appropriate format also.
|
|
bitmap * bm_d3d_lock( int handle, ubyte bpp, ubyte flags )
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
bitmap *bmp;
|
|
bitmap_entry *be;
|
|
|
|
int bitmapnum = handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
// if we're on a standalone server, aways for it to lock to 8 bits
|
|
if(Is_standalone){
|
|
bpp = 8;
|
|
flags = 0;
|
|
}
|
|
// otherwise do it as normal
|
|
else if(flags & BMP_AABITMAP){
|
|
// Assert( bpp == 8 );
|
|
}
|
|
else {
|
|
Assert( bpp == 16 );
|
|
}
|
|
|
|
be = &bm_bitmaps[bitmapnum];
|
|
bmp = &be->bm;
|
|
|
|
// If you hit this assert, chances are that someone freed the
|
|
// wrong bitmap and now someone is trying to use that bitmap.
|
|
// See John.
|
|
Assert( be->type != BM_TYPE_NONE );
|
|
|
|
// Increment ref count for bitmap since lock was made on it.
|
|
Assert(be->ref_count >= 0);
|
|
be->ref_count++; // Lock it before we page in data; this prevents a callback from freeing this
|
|
// as it gets read in
|
|
|
|
// Mark this bitmap as used this frame
|
|
|
|
// if bitmap hasn't been loaded yet, then load it from disk
|
|
// reread the bitmap from disk under certain conditions
|
|
if(be->type > BM_TYPE_32_BIT_FORMATS)
|
|
{
|
|
if(d3d_bitmap_entry[bitmapnum].tinterface == NULL)
|
|
{
|
|
switch ( be->type ) {
|
|
|
|
// We'll let D3DX handle this
|
|
case BM_TYPE_JPG:
|
|
case BM_TYPE_DDS:
|
|
case BM_TYPE_TGA:
|
|
{
|
|
d3d_bitmap_entry[bitmapnum].tinterface =
|
|
(IDirect3DBaseTexture8 *) d3d_lock_d3dx_types(be->filename, be->type, flags, bitmapnum);
|
|
break;
|
|
}
|
|
default:
|
|
Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", be->type );
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
else if (be->type == BM_TYPE_PCX)
|
|
{
|
|
if(d3d_bitmap_entry[bitmapnum].tinterface == NULL)
|
|
{
|
|
// select proper format
|
|
if(flags & BMP_AABITMAP){
|
|
BM_SELECT_ALPHA_TEX_FORMAT();
|
|
} else if(flags & BMP_TEX_ANY){
|
|
BM_SELECT_TEX_FORMAT();
|
|
} else {
|
|
BM_SELECT_SCREEN_FORMAT();
|
|
}
|
|
|
|
bm_d3d_lock_pcx( handle, bitmapnum, be, bmp, bpp, flags );
|
|
}
|
|
}
|
|
*/
|
|
else if ( (bmp->data == 0) || (bpp != bmp->bpp && bmp->bpp != 32)) {
|
|
Assert(be->ref_count == 1);
|
|
|
|
if ( be->type != BM_TYPE_USER ) {
|
|
if ( bmp->data == 0 ) {
|
|
nprintf (("BmpMan","Loading %s for the first time.\n", be->filename));
|
|
} else if ( bpp != bmp->bpp ) {
|
|
nprintf (("BmpMan","Reloading %s from bitdepth %d to bitdepth %d\n", be->filename, bmp->bpp, bpp));
|
|
}
|
|
}
|
|
|
|
// select proper format
|
|
if(flags & BMP_AABITMAP){
|
|
BM_SELECT_ALPHA_TEX_FORMAT();
|
|
} else if(flags & BMP_TEX_ANY){
|
|
BM_SELECT_TEX_FORMAT();
|
|
} else {
|
|
BM_SELECT_SCREEN_FORMAT();
|
|
}
|
|
|
|
switch ( be->type ) {
|
|
case BM_TYPE_PCX:
|
|
bm_d3d_lock_pcx( handle, bitmapnum, be, bmp, bpp, flags );
|
|
break;
|
|
|
|
case BM_TYPE_ANI:
|
|
bm_d3d_lock_ani( handle, bitmapnum, be, bmp, bpp, flags );
|
|
break;
|
|
|
|
case BM_TYPE_USER:
|
|
bm_d3d_lock_user( handle, bitmapnum, be, bmp, bpp, flags );
|
|
break;
|
|
default:
|
|
Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", be->type );
|
|
return NULL;
|
|
}
|
|
|
|
// always go back to screen format
|
|
BM_SELECT_SCREEN_FORMAT();
|
|
}
|
|
|
|
if ( be->type == BM_TYPE_ANI ) {
|
|
int i,first = bm_bitmaps[bitmapnum].info.ani.first_frame;
|
|
|
|
for ( i=0; i< bm_bitmaps[first].info.ani.num_frames; i++ ) {
|
|
// Mark all the bitmaps in this bitmap or animation as recently used
|
|
bm_bitmaps[first+i].last_used = timer_get_milliseconds();
|
|
|
|
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
|
|
bm_bitmaps[first+i].used_flags = flags;
|
|
}
|
|
} else {
|
|
// Mark all the bitmaps in this bitmap or animation as recently used
|
|
be->last_used = timer_get_milliseconds();
|
|
|
|
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
|
|
be->used_flags = flags;
|
|
}
|
|
|
|
return bmp;
|
|
}
|
|
|
|
// Unlocks a bitmap
|
|
//
|
|
// Decrements the ref_count member of the bitmap_entry struct. A bitmap can only be unloaded
|
|
// when the ref_count is 0.
|
|
//
|
|
void bm_d3d_unlock( int handle )
|
|
{
|
|
Assert(bm_d3d_inited);
|
|
|
|
bitmap_entry *be;
|
|
bitmap *bmp;
|
|
|
|
int bitmapnum = handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[bitmapnum].handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
Assert(bitmapnum >= 0 && bitmapnum < MAX_BITMAPS);
|
|
|
|
be = &bm_bitmaps[bitmapnum];
|
|
bmp = &be->bm;
|
|
|
|
be->ref_count--;
|
|
Assert(be->ref_count >= 0); // Trying to unlock data more times than lock was called!!!
|
|
|
|
}
|
|
|
|
void bm_d3d_get_palette(int handle, ubyte *pal, char *name)
|
|
{
|
|
char *filename;
|
|
int w,h;
|
|
|
|
int n= handle % MAX_BITMAPS;
|
|
Assert( bm_bitmaps[n].handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
filename = bm_bitmaps[n].filename;
|
|
|
|
if (name) {
|
|
strcpy( name, filename );
|
|
}
|
|
|
|
int pcx_error=pcx_read_header( filename, &w, &h, pal );
|
|
if ( pcx_error != PCX_ERROR_NONE ){
|
|
// Error(LOCATION, "Couldn't open '%s'\n", filename );
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// bm_release() - unloads the bitmap's data and entire slot, so bitmap 'n' won't be valid anymore
|
|
//
|
|
// parameters: n => index into bm_bitmaps ( index returned from bm_load() or bm_create() )
|
|
//
|
|
// returns: nothing
|
|
|
|
void bm_d3d_release(int handle)
|
|
{
|
|
bitmap_entry *be;
|
|
|
|
int n = handle % MAX_BITMAPS;
|
|
|
|
Assert(n >= 0 && n < MAX_BITMAPS);
|
|
be = &bm_bitmaps[n];
|
|
|
|
if ( bm_bitmaps[n].type == BM_TYPE_NONE ) {
|
|
return; // Already been released?
|
|
}
|
|
|
|
if ( bm_bitmaps[n].type != BM_TYPE_USER ) {
|
|
return;
|
|
}
|
|
|
|
Assert( be->handle == handle ); // INVALID BITMAP HANDLE
|
|
|
|
// If it is locked, cannot free it.
|
|
if (be->ref_count != 0) {
|
|
nprintf(("BmpMan", "tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
|
|
return;
|
|
}
|
|
|
|
bm_d3d_free_data(n);
|
|
|
|
if ( bm_bitmaps[n].type == BM_TYPE_USER ) {
|
|
bm_bitmaps[n].info.user.data = NULL;
|
|
bm_bitmaps[n].info.user.bpp = 0;
|
|
}
|
|
|
|
bm_bitmaps[n].type = BM_TYPE_NONE;
|
|
|
|
// Fill in bogus structures!
|
|
|
|
// For debugging:
|
|
strcpy( bm_bitmaps[n].filename, "IVE_BEEN_RELEASED!" );
|
|
bm_bitmaps[n].signature = 0xDEADBEEF; // a unique signature identifying the data
|
|
bm_bitmaps[n].palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
|
|
|
|
// bookeeping
|
|
bm_bitmaps[n].ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
|
|
|
|
// Bitmap info
|
|
bm_bitmaps[n].bm.w = bm_bitmaps[n].bm.h = -1;
|
|
|
|
// Stuff needed for animations
|
|
// Stuff needed for user bitmaps
|
|
memset( &bm_bitmaps[n].info, 0, sizeof(bm_extra_info) );
|
|
|
|
bm_bitmaps[n].handle = -1;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// bm_unload() - unloads the data, but not the bitmap info.
|
|
//
|
|
// parameters: n => index into bm_bitmaps ( index returned from bm_load() or bm_create() )
|
|
//
|
|
// returns: 0 => unload failed
|
|
// 1 => unload successful
|
|
//
|
|
int bm_d3d_unload( int handle )
|
|
{
|
|
bitmap_entry *be;
|
|
bitmap *bmp;
|
|
|
|
int n = handle % MAX_BITMAPS;
|
|
|
|
Assert(n >= 0 && n < MAX_BITMAPS);
|
|
be = &bm_bitmaps[n];
|
|
bmp = &be->bm;
|
|
|
|
if ( be->type == BM_TYPE_NONE ) {
|
|
return 0; // Already been released
|
|
}
|
|
|
|
Assert( be->handle == handle ); // INVALID BITMAP HANDLE!
|
|
|
|
if(stricmp("2_Credits.jpg", be->filename) == 0)
|
|
{
|
|
mprintf(("unloading 2_Credits.jpg\n"));
|
|
}
|
|
|
|
// If it is locked, cannot free it.
|
|
if (be->ref_count != 0) {
|
|
nprintf(("BmpMan", "tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
|
|
return 0;
|
|
}
|
|
|
|
nprintf(("BmpMan", "unloading %s. %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
|
|
bm_d3d_free_data(n); // clears flags, bbp, data, etc
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// unload all used bitmaps
|
|
void bm_d3d_unload_all()
|
|
{
|
|
for (int i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
|
|
bm_unload(bm_bitmaps[i].handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Marks a texture as being used for this level
|
|
void bm_d3d_page_in_texture( int bitmapnum, int nframes )
|
|
{
|
|
int n = bitmapnum % MAX_BITMAPS;
|
|
for (int i=0; i<nframes;i++ ) {
|
|
|
|
bm_bitmaps[n+i].preloaded = 1;
|
|
|
|
if ( D3D_enabled ) {
|
|
bm_bitmaps[n+i].used_flags = BMP_TEX_OTHER;
|
|
} else {
|
|
bm_bitmaps[n+i].used_flags = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Marks a texture as being used for this level
|
|
// If num_frames is passed, assume this is an animation
|
|
void bm_d3d_page_in_nondarkening_texture( int bitmapnum, int nframes )
|
|
{
|
|
int n = bitmapnum % MAX_BITMAPS;
|
|
for (int i=0; i<nframes;i++ ) {
|
|
|
|
bm_bitmaps[n+i].preloaded = 4;
|
|
|
|
if ( D3D_enabled ) {
|
|
bm_bitmaps[n+i].used_flags = BMP_TEX_NONDARK;
|
|
} else {
|
|
bm_bitmaps[n+i].used_flags = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// marks a texture as being a transparent textyre used for this level
|
|
// Marks a texture as being used for this level
|
|
// If num_frames is passed, assume this is an animation
|
|
void bm_d3d_page_in_xparent_texture( int bitmapnum, int nframes)
|
|
{
|
|
int n = bitmapnum % MAX_BITMAPS;
|
|
for (int i=0; i<nframes;i++ ) {
|
|
|
|
bm_bitmaps[n+i].preloaded = 3;
|
|
|
|
if ( D3D_enabled ) {
|
|
bm_bitmaps[n+i].used_flags = BMP_TEX_XPARENT;
|
|
} else {
|
|
bm_bitmaps[n+i].used_flags = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Marks an aabitmap as being used for this level
|
|
void bm_d3d_page_in_aabitmap( int bitmapnum, int nframes )
|
|
{
|
|
int n = bitmapnum % MAX_BITMAPS;
|
|
for (int i=0; i<nframes;i++ ) {
|
|
|
|
bm_bitmaps[n+i].preloaded = 2;
|
|
|
|
if ( D3D_enabled ) {
|
|
bm_bitmaps[n+i].used_flags = BMP_AABITMAP;
|
|
} else {
|
|
bm_bitmaps[n+i].used_flags = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Tell the bitmap manager to start keeping track of what bitmaps are used where.
|
|
void bm_d3d_page_in_start()
|
|
{
|
|
// Mark all as inited
|
|
for (int i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
|
|
bm_unload(bm_bitmaps[i].handle);
|
|
}
|
|
bm_bitmaps[i].preloaded = 0;
|
|
bm_bitmaps[i].used_flags = 0;
|
|
}
|
|
|
|
GlobalD3DVars::lpD3DDevice->ResourceManagerDiscardBytes(0);
|
|
}
|
|
|
|
void bm_d3d_page_in_stop()
|
|
{
|
|
int ship_info_index;
|
|
extern void gr_d3d_preload_init();
|
|
extern int gr_d3d_preload(int bitmap_num, int is_aabitmap );
|
|
int i;
|
|
|
|
nprintf(( "BmpInfo","BMPMAN: Loading all used bitmaps.\n" ));
|
|
|
|
// Load all the ones that are supposed to be loaded for this level.
|
|
int n = 0;
|
|
|
|
int d3d_preloading = 1;
|
|
gr_d3d_preload_init();
|
|
|
|
for (i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
|
|
if ( bm_bitmaps[i].preloaded ) {
|
|
|
|
#ifdef BMPMAN_SPECIAL_NONDARK
|
|
// if this is a texture, check to see if a ship uses it
|
|
ship_info_index = ship_get_texture(bm_bitmaps[i].handle);
|
|
// use the colors from this ship
|
|
if((ship_info_index >= 0) && (Ship_info[ship_info_index].num_nondark_colors > 0)){
|
|
// mprintf(("Using custom pixels for %s\n", Ship_info[ship_info_index].name));
|
|
palman_set_nondarkening(Ship_info[ship_info_index].nondark_colors, Ship_info[ship_info_index].num_nondark_colors);
|
|
}
|
|
// use the colors from the default table
|
|
else {
|
|
// mprintf(("Using default pixels\n"));
|
|
palman_set_nondarkening(Palman_non_darkening_default, Palman_num_nondarkening_default);
|
|
}
|
|
#endif
|
|
|
|
// if preloaded == 3, load it as an xparent texture
|
|
if(bm_bitmaps[i].used_flags == BMP_AABITMAP){
|
|
bm_lock( bm_bitmaps[i].handle, 8, bm_bitmaps[i].used_flags );
|
|
} else {
|
|
bm_lock( bm_bitmaps[i].handle, 16, bm_bitmaps[i].used_flags );
|
|
}
|
|
bm_unlock( bm_bitmaps[i].handle );
|
|
|
|
if ( d3d_preloading ) {
|
|
if ( !gr_d3d_preload(bm_bitmaps[i].handle, (bm_bitmaps[i].preloaded==2) ) ) {
|
|
mprintf(( "Out of VRAM. Done preloading.\n" ));
|
|
d3d_preloading = 0;
|
|
}
|
|
}
|
|
|
|
n++;
|
|
}
|
|
}
|
|
game_busy();
|
|
}
|
|
nprintf(( "BmpInfo","BMPMAN: Loaded %d bitmaps that are marked as used for this level.\n", n ));
|
|
|
|
int total_bitmaps = 0;
|
|
for (i = 0; i < MAX_BITMAPS; i++) {
|
|
if ( bm_bitmaps[i].type != BM_TYPE_NONE ) {
|
|
total_bitmaps++;
|
|
}
|
|
if ( bm_bitmaps[i].type == BM_TYPE_USER ) {
|
|
mprintf(( "User bitmap '%s'\n", bm_bitmaps[i].filename ));
|
|
}
|
|
}
|
|
|
|
mprintf(( "Bmpman: %d/%d bitmap slots in use.\n", total_bitmaps, MAX_BITMAPS ));
|
|
}
|
|
|
|
int bm_d3d_get_cache_slot( int bitmap_id, int separate_ani_frames )
|
|
{
|
|
int n = bitmap_id % MAX_BITMAPS;
|
|
|
|
Assert( bm_bitmaps[n].handle == bitmap_id ); // INVALID BITMAP HANDLE
|
|
|
|
bitmap_entry *be = &bm_bitmaps[n];
|
|
|
|
if ( (!separate_ani_frames) && (be->type == BM_TYPE_ANI) ) {
|
|
return be->info.ani.first_frame;
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
// get the rgba components of a pixel, any of the parameters can be NULL
|
|
void bm_d3d_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a)
|
|
{
|
|
extern int D3D_32bit;
|
|
int bit_32 = 0;
|
|
|
|
// pick a byte size - 32 bits only if 32 bit mode d3d and screen format
|
|
if(D3D_32bit && (Gr_current_red == &Gr_red)){
|
|
bit_32 = 1;
|
|
}
|
|
|
|
if(r != NULL){
|
|
if(bit_32){
|
|
*r = ubyte(( (*((uint*)pixel) & Gr_current_red->mask)>>Gr_current_red->shift)*Gr_current_red->scale);
|
|
} else {
|
|
*r = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_red->mask)>>Gr_current_red->shift)*Gr_current_red->scale);
|
|
}
|
|
}
|
|
if(g != NULL){
|
|
if(bit_32){
|
|
*g = ubyte(( (*((uint*)pixel) & Gr_current_green->mask) >>Gr_current_green->shift)*Gr_current_green->scale);
|
|
} else {
|
|
*g = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_green->mask) >>Gr_current_green->shift)*Gr_current_green->scale);
|
|
}
|
|
}
|
|
if(b != NULL){
|
|
if(bit_32){
|
|
*b = ubyte(( (*((uint*)pixel) & Gr_current_blue->mask)>>Gr_current_blue->shift)*Gr_current_blue->scale);
|
|
} else {
|
|
*b = ubyte(( ( ((ushort*)pixel)[0] & Gr_current_blue->mask)>>Gr_current_blue->shift)*Gr_current_blue->scale);
|
|
}
|
|
}
|
|
|
|
// get the alpha value - this is never asked for
|
|
if(a != NULL){
|
|
*a = 1;
|
|
|
|
Assert(!bit_32);
|
|
if(!( ((ushort*)pixel)[0] & 0x8000)){
|
|
*a = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// given a bitmap and a section, return the size (w, h)
|
|
void bm_d3d_get_section_size(int bitmapnum, int sx, int sy, int *w, int *h)
|
|
{
|
|
int bw, bh;
|
|
|
|
// bogus input?
|
|
Assert((w != NULL) && (h != NULL));
|
|
if((w == NULL) || (h == NULL)){
|
|
return;
|
|
}
|
|
|
|
// get bitmap info
|
|
bm_get_info(bitmapnum, &bw, &bh, NULL, NULL, NULL, NULL);
|
|
|
|
// determine the width and height of this section
|
|
*w = bw;
|
|
*h = bh;
|
|
}
|