mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
306 lines
8.1 KiB
C++
306 lines
8.1 KiB
C++
#include <string.h>
|
|
#include <core/defines.h>
|
|
#include <core/debug.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/file/filesys.h>
|
|
#include "nx_init.h"
|
|
#include "chars.h"
|
|
#include "texture.h"
|
|
#include "render.h"
|
|
|
|
namespace NxXbox
|
|
{
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
sTexture::sTexture()
|
|
{
|
|
pD3DTexture = NULL;
|
|
pD3DPalette = NULL;
|
|
pD3DSurface = NULL; // If used as a render target.
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
sTexture::~sTexture()
|
|
{
|
|
ULONG rr;
|
|
|
|
if( pD3DTexture )
|
|
{
|
|
rr = pD3DTexture->Release();
|
|
Dbg_Assert( rr == 0 );
|
|
|
|
// Ensure that this texture is no longer referenced in the EngineGlobals.
|
|
for( int p = 0; p < 4; ++p )
|
|
{
|
|
if( EngineGlobals.p_texture[p] == pD3DTexture )
|
|
{
|
|
set_texture( p, NULL );
|
|
}
|
|
}
|
|
}
|
|
if( pD3DPalette )
|
|
{
|
|
rr = pD3DPalette->Release();
|
|
Dbg_Assert( rr == 0 );
|
|
}
|
|
if( pD3DSurface )
|
|
{
|
|
rr = pD3DSurface->Release();
|
|
Dbg_Assert( rr == 0 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
void sTexture::Set( int pass )
|
|
{
|
|
// Set this texture as the active texture for a specific pass.
|
|
set_texture( pass, pD3DTexture, pD3DPalette );
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
bool sTexture::SetRenderTarget( int width, int height, int depth, int z_depth )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if( pD3DTexture )
|
|
{
|
|
pD3DTexture->Release();
|
|
}
|
|
if( pD3DPalette )
|
|
{
|
|
pD3DPalette->Release();
|
|
}
|
|
|
|
// Create the shadow buffer (essentially just a depth buffer).
|
|
hr = D3DDevice_CreateTexture( width, height, 1, 0, D3DFMT_LIN_D24S8, 0, &pD3DTexture );
|
|
Dbg_Assert( hr == D3D_OK );
|
|
if( hr == D3D_OK )
|
|
{
|
|
// Set fields to reflect surface characteristics.
|
|
Checksum = 0;
|
|
BaseWidth = ActualWidth = width;
|
|
BaseHeight = ActualHeight = height;
|
|
Levels = 1;
|
|
TexelDepth = depth;
|
|
PaletteDepth = 0;
|
|
DXT = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
// Eeeek - the .img contains PS2 specific register values for bit depth.
|
|
// Use these values to convert them.
|
|
#define PSMCT32 0x00
|
|
#define PSMCT24 0x01
|
|
#define PSMCT16 0x02
|
|
#define PSMCT16S 0x0A
|
|
#define PS_GPU24 0x12
|
|
#define PSMT8 0x13
|
|
#define PSMT4 0x14
|
|
#define PSMT8H 0x1B
|
|
#define PSMT4HL 0x24
|
|
#define PSMT4HH 0x2C
|
|
#define PSMZ32 0x30
|
|
#define PSMZ24 0x31
|
|
#define PSMZ16 0x32
|
|
#define PSMZ16S 0x3A
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
static bool is_power_of_two( uint32 a )
|
|
{
|
|
if( a == 0 )
|
|
{
|
|
return false;
|
|
}
|
|
return (( a & ( a - 1 )) == 0 );
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
sTexture *LoadTexture( const char *p_filename )
|
|
{
|
|
struct sIMGHeader
|
|
{
|
|
uint32 version;
|
|
uint32 checksum;
|
|
uint32 width;
|
|
uint32 height;
|
|
uint32 bit_depth;
|
|
uint32 clut_bit_depth;
|
|
uint16 original_width;
|
|
uint16 original_height;
|
|
uint32 palette_data_size;
|
|
};
|
|
|
|
void *p_FH = File::Open( p_filename, "rb" );
|
|
|
|
if( p_FH )
|
|
{
|
|
// Read header.
|
|
sIMGHeader header;
|
|
File::Read( &header, sizeof( sIMGHeader ), 1, p_FH );
|
|
|
|
// Bits per texel and palette size.
|
|
switch( header.bit_depth )
|
|
{
|
|
case PSMCT32:
|
|
header.bit_depth = 32;
|
|
break;
|
|
case PSMCT16:
|
|
header.bit_depth = 16;
|
|
break;
|
|
case PSMT8:
|
|
header.bit_depth = 8;
|
|
break;
|
|
default:
|
|
Dbg_Assert( 0 );
|
|
}
|
|
|
|
// Bits per clut entry.
|
|
if( header.bit_depth < 16 )
|
|
{
|
|
switch( header.clut_bit_depth )
|
|
{
|
|
case PSMCT32:
|
|
header.clut_bit_depth = 32;
|
|
break;
|
|
default:
|
|
Dbg_Assert( 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
header.clut_bit_depth = 0;
|
|
}
|
|
|
|
{
|
|
// Create the texture object.
|
|
sTexture *p_texture = new sTexture();
|
|
|
|
// Create palette if required.
|
|
if( header.clut_bit_depth == 0 )
|
|
{
|
|
p_texture->pD3DPalette = NULL;
|
|
}
|
|
else
|
|
{
|
|
if( D3D_OK != D3DDevice_CreatePalette( D3DPALETTE_256, &p_texture->pD3DPalette ))
|
|
{
|
|
Dbg_Assert( 0 );
|
|
}
|
|
|
|
// Read clut bitmap data.
|
|
D3DCOLOR *p_clut;
|
|
p_texture->pD3DPalette->Lock( &p_clut, 0 );
|
|
|
|
int len = File::Read( p_clut, header.palette_data_size, 1, p_FH );
|
|
Dbg_MsgAssert( len == header.palette_data_size, ( "Couldn't read clut from texture file %s", p_filename ));
|
|
}
|
|
|
|
// Textures of width 512 and above will not have been resized. This means they cannot be in a swizzled format.
|
|
// bool arbitrary_texture_size = ( header.original_width >= 512 );
|
|
bool arbitrary_texture_size = false;
|
|
|
|
if( !is_power_of_two( header.width ) || !is_power_of_two( header.height ))
|
|
arbitrary_texture_size = true;
|
|
|
|
// Create texture resource. Linear for arbitrary sized textures, swizzled for standard sizes.
|
|
uint32 num_bytes;
|
|
if( arbitrary_texture_size )
|
|
{
|
|
if( D3D_OK != D3DDevice_CreateTexture( header.original_width,
|
|
header.original_height,
|
|
1,
|
|
0,
|
|
( header.bit_depth <= 8 ) ? D3DFMT_P8 : (( header.bit_depth == 16 ) ? D3DFMT_LIN_A1R5G5B5 : D3DFMT_LIN_A8R8G8B8 ),
|
|
0,
|
|
&p_texture->pD3DTexture ))
|
|
{
|
|
Dbg_Assert( 0 );
|
|
}
|
|
p_texture->BaseWidth = header.original_width;
|
|
p_texture->BaseHeight = header.original_height;
|
|
p_texture->ActualWidth = header.original_width;
|
|
p_texture->ActualHeight = header.original_height;
|
|
num_bytes = ((( header.bit_depth / 8 ) * ( header.original_width ) * ( header.original_height )) + 3 ) & 0xFFFFFFFC;
|
|
}
|
|
else
|
|
{
|
|
if( D3D_OK != D3DDevice_CreateTexture( header.width,
|
|
header.height,
|
|
1,
|
|
0,
|
|
( header.bit_depth <= 8 ) ? D3DFMT_P8 : (( header.bit_depth == 16 ) ? D3DFMT_A1R5G5B5 : D3DFMT_A8R8G8B8 ),
|
|
0,
|
|
&p_texture->pD3DTexture ))
|
|
{
|
|
Dbg_Assert( 0 );
|
|
}
|
|
p_texture->BaseWidth = (uint16)header.width;
|
|
p_texture->BaseHeight = (uint16)header.height;
|
|
p_texture->ActualWidth = header.original_width;
|
|
p_texture->ActualHeight = header.original_height;
|
|
num_bytes = ((( header.bit_depth / 8 ) * header.width * header.height ) + 3 ) & 0xFFFFFFFC;
|
|
}
|
|
|
|
// Lock the texture so we can read data into it directly.
|
|
D3DLOCKED_RECT locked_rect;
|
|
if( D3D_OK != p_texture->pD3DTexture->LockRect( 0, &locked_rect, NULL, 0 ))
|
|
{
|
|
Dbg_Assert( 0 );
|
|
}
|
|
|
|
// Read texture bitmap data directly into texture.
|
|
int len = File::Read( locked_rect.pBits, num_bytes, 1, p_FH );
|
|
Dbg_MsgAssert( len == num_bytes, ( "couldn't read texture data from texture file %s", p_filename ));
|
|
|
|
File::Close( p_FH );
|
|
|
|
// Set up some member values.
|
|
p_texture->PaletteDepth = (uint8)header.clut_bit_depth;
|
|
p_texture->TexelDepth = (uint8)header.bit_depth;
|
|
p_texture->DXT = 0;
|
|
p_texture->Levels = 1;
|
|
|
|
return p_texture;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
} // namespace NxXbox
|
|
|