Files
source/Standard Gaming Platform/himage.cpp
T
Overhaul 7a27e7105d New attack busy system
Added missing #includes

Added LUA scripting and console

Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain

Fixed signedness of many grid variables used in GetMouseMapPos calls

Fixed enemy weapon choosing:  Sometimes a mortar is chosen but later rejected, but the grenade class was not reset.  Caused assertion failure

Added checks so enemies don't try to chuck RPG grenades with their hands

Now possible to shoot a someone in the head if he's in water

Fixed InitSightArrays to also clear soldier interrupt duel points.  This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called.

Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have

Removed early setting of muzzle flash.  This would allow enemies to get an interrupt before you even fired.

Fixed item dropping by AI.  If AI tried to drop something while standing it would cause deadlock

Change to greatly speed up closing the sector inventory window in an unloaded sector

Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting


Check builddefines.h for the conditional flags.  Of greatest interest might be LUA_CONSOLE.  This will cause the game to bring up a command console when run.  However this console is severely lacking in many areas.  If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated.  The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus.

LUA scripting is very limited, basically just proof of concept.  There is one global variable, the Soldiers array.  An array index gives you the soldier in that slot in the currently loaded sector.  The soldier has a few things that can be accessed:  name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid)


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-06-09 09:01:04 +00:00

1016 lines
27 KiB
C++

#ifdef JA2_PRECOMPILED_HEADERS
#include "JA2 SGP ALL.H"
#elif defined( WIZ8_PRECOMPILED_HEADERS )
#include "WIZ8 SGP ALL.H"
#else
#include "builddefines.h"
#include <math.h>
#include <stdlib.h>
#include "types.h"
#include "string.h"
#include "debug.h"
#include "fileman.h"
#include "himage.h"
#include "impTGA.h"
#include "pcx.h"
#include "STCI.h"
#include "wcheck.h"
#include "Compression.h"
#include "vobject.h"
#endif
// This is the color substituted to keep a 24bpp -> 16bpp color
// from going transparent (0x0000) -- DB
#define BLACK_SUBSTITUTE 0x0001
UINT16 gusAlphaMask = 0;
UINT16 gusRedMask = 0;
UINT16 gusGreenMask = 0;
UINT16 gusBlueMask = 0;
INT16 gusRedShift = 0;
INT16 gusBlueShift = 0;
INT16 gusGreenShift = 0;
// this funky union is used for fast 16-bit pixel format conversions
typedef union
{
struct
{
UINT16 usLower;
UINT16 usHigher;
};
UINT32 uiValue;
} SplitUINT32;
HIMAGE CreateImage( SGPFILENAME ImageFile, UINT16 fContents )
{
HIMAGE hImage = NULL;
SGPFILENAME Extension;
CHAR8 ExtensionSep[] = ".";
STR StrPtr;
UINT32 iFileLoader;
// Depending on extension of filename, use different image readers
// Get extension
StrPtr = strstr( ImageFile, ExtensionSep );
if ( StrPtr == NULL )
{
// No extension given, use default internal loader extension
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "No extension given, using default" );
strcat( ImageFile, ".PCX" );
strcpy( Extension, ".PCX" );
}
else
{
strcpy( Extension, StrPtr+1 );
}
// Determine type from Extension
do
{
iFileLoader = UNKNOWN_FILE_READER;
if ( _stricmp( Extension, "PCX" ) == 0 )
{
iFileLoader = PCX_FILE_READER;
break;
}
if ( _stricmp( Extension, "TGA" ) == 0 )
{
iFileLoader = TGA_FILE_READER;
break;
}
if ( _stricmp( Extension, "STI" ) == 0 )
{
iFileLoader = STCI_FILE_READER;
break;
}
} while ( FALSE );
// Determine if resource exists before creating image structure
if ( !FileExists( ImageFile ) )
{
//If in debig, make fatal!
#ifdef JA2
#ifdef _DEBUG
//FatalError( "Resource file %s does not exist.", ImageFile );
#endif
#endif
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, String("Resource file %s does not exist.", ImageFile) );
return( NULL );
}
// Create memory for image structure
hImage = (HIMAGE)MemAlloc( sizeof( image_type ) );
AssertMsg( hImage, "Failed to allocate memory for hImage in CreateImage");
// Initialize some values
memset( hImage, 0, sizeof( image_type ) );
//hImage->fFlags = 0;
// Set data pointers to NULL
//hImage->pImageData = NULL;
//hImage->pPalette = NULL;
//hImage->pui16BPPPalette = NULL;
// Set filename and loader
strcpy( hImage->ImageFile, ImageFile );
hImage->iFileLoader = iFileLoader;
if ( !LoadImageData( hImage, fContents ) )
{
return( NULL );
}
// All is fine, image is loaded and allocated, return pointer
return( hImage );
}
BOOLEAN DestroyImage( HIMAGE hImage )
{
Assert( hImage != NULL );
// First delete contents
ReleaseImageData( hImage, IMAGE_ALLDATA );//hImage->fFlags );
// Now free structure
MemFree( hImage );
return( TRUE );
}
BOOLEAN ReleaseImageData( HIMAGE hImage, UINT16 fContents )
{
Assert( hImage != NULL );
if ( (fContents & IMAGE_PALETTE) && (hImage->fFlags & IMAGE_PALETTE) )
{
//Destroy palette
if( hImage->pPalette != NULL )
{
MemFree( hImage->pPalette );
hImage->pPalette = NULL;
}
if ( hImage->pui16BPPPalette != NULL )
{
MemFree( hImage->pui16BPPPalette );
hImage->pui16BPPPalette = NULL;
}
// Remove contents flag
hImage->fFlags = hImage->fFlags ^ IMAGE_PALETTE;
}
if ( (fContents & IMAGE_BITMAPDATA) && (hImage->fFlags & IMAGE_BITMAPDATA) )
{
//Destroy image data
Assert( hImage->pImageData != NULL );
MemFree( hImage->pImageData );
hImage->pImageData = NULL;
if (hImage->usNumberOfObjects > 0)
{
MemFree( hImage->pETRLEObject );
}
// Remove contents flag
hImage->fFlags = hImage->fFlags ^ IMAGE_BITMAPDATA;
}
if ( (fContents & IMAGE_APPDATA) && (hImage->fFlags & IMAGE_APPDATA) )
{
// get rid of the APP DATA
if ( hImage->pAppData != NULL )
{
MemFree( hImage->pAppData );
hImage->fFlags &= (~IMAGE_APPDATA);
}
}
return( TRUE );
}
BOOLEAN LoadImageData( HIMAGE hImage, UINT16 fContents )
{
BOOLEAN fReturnVal = FALSE;
Assert( hImage != NULL );
// Switch on file loader
switch( hImage->iFileLoader )
{
case TGA_FILE_READER:
fReturnVal = LoadTGAFileToImage( hImage, fContents );
break;
case PCX_FILE_READER:
fReturnVal = LoadPCXFileToImage( hImage, fContents );
break;
case STCI_FILE_READER:
fReturnVal = LoadSTCIFileToImage( hImage, fContents );
break;
default:
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Unknown image loader was specified." );
}
if ( !fReturnVal )
{
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Error occured while reading image data." );
}
return( fReturnVal );
}
BOOLEAN CopyImageToBuffer( HIMAGE hImage, UINT32 fBufferType, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
// Use blitter based on type of image
Assert( hImage != NULL );
if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_8BPP )
{
#ifndef NO_ZLIB_COMPRESSION
if ( hImage->fFlags & IMAGE_COMPRESSED )
{
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying Compressed 8 BPP Imagery." );
return( Copy8BPPCompressedImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
#endif
// Default do here
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying 8 BPP Imagery." );
return ( Copy8BPPImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_16BPP )
{
#ifndef NO_ZLIB_COMPRESSION
if ( hImage->fFlags & IMAGE_COMPRESSED )
{
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying Compressed 8 BPP Imagery to 16BPP Buffer." );
return ( Copy8BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
#endif
// Default do here
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying 8 BPP Imagery to 16BPP Buffer." );
return ( Copy8BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
if ( hImage->ubBitDepth == 16 && fBufferType == BUFFER_16BPP )
{
#ifndef NO_ZLIB_COMPRESSION
if ( hImage->fFlags & IMAGE_COMPRESSED )
{
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying Compressed 16 BPP Imagery." );
return( Copy16BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
#endif
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying 16 BPP Imagery." );
return( Copy16BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
}
return( FALSE );
}
#ifndef NO_ZLIB_COMPRESSION
BOOLEAN Copy8BPPCompressedImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
UINT32 uiNumLines;
UINT32 uiLineSize;
UINT32 uiCnt;
UINT8 * pDest;
UINT32 uiDestStart;
UINT8 * pScanLine;
PTR pDecompPtr;
UINT32 uiDecompressed;
// Assertions
Assert( hImage != NULL );
Assert( hImage->pCompressedImageData != NULL );
// Validations
CHECKF( usX >= 0 );
CHECKF( usX < usDestWidth );
CHECKF( usY >= 0 );
CHECKF( usY < usDestHeight );
CHECKF( srcRect->iRight > srcRect->iLeft );
CHECKF( srcRect->iBottom > srcRect->iTop );
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "8BPP to 8BPP Compressed Blitter Called!" );
// determine where to start Copying and rectangle size
uiDestStart = usY * usDestWidth + usX;
uiNumLines = srcRect->iBottom - srcRect->iTop;
uiLineSize = srcRect->iRight - srcRect->iLeft;
Assert( usDestWidth >= uiLineSize );
Assert( usDestHeight >= uiNumLines );
pDest = (UINT8 *) pDestBuf + uiDestStart;
// Copying a portion of a compressed image is rather messy
// because we have to decompress past all the data we want
// to skip.
// To keep memory requirements small and regular, we will
// decompress one scanline at a time even if none of the data will
// be blitted (but stop when the bottom line of the rectangle
// to blit has been done).
// initialize the decompression routines
pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight );
CHECKF( pDecompPtr );
// Allocate memory for one scanline
pScanLine = MemAlloc( hImage->usWidth );
CHECKF( pScanLine );
// go past all the scanlines we don't need to process
for (uiCnt = 0; uiCnt < (UINT32) srcRect->iTop; uiCnt++)
{
uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
Assert( uiDecompressed == hImage->usWidth );
}
// now we start Copying
for (uiCnt = 0; uiCnt < uiNumLines - 1; uiCnt++)
{
// decompress a scanline
uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
Assert( uiDecompressed == hImage->usWidth );
// and blit
// memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize );
pDest += usDestWidth;
}
// decompress the last scanline and blit
uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
Assert( uiDecompressed == hImage->usWidth );
// memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize );
DecompressFini( pDecompPtr );
return( TRUE );
}
BOOLEAN Copy8BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
UINT32 uiNumLines;
UINT32 uiLineSize;
UINT32 uiLine;
UINT32 uiCol;
UINT16 * pDest;
UINT16 * pDestTemp;
UINT32 uiDestStart;
UINT8 * pScanLine;
UINT8 * pScanLineTemp;
PTR pDecompPtr;
UINT32 uiDecompressed;
UINT16 * p16BPPPalette;
// Assertions
Assert( hImage != NULL );
Assert( hImage->pCompressedImageData != NULL );
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Start check" );
// Validations
CHECKF( usX >= 0 );
CHECKF( usX < usDestWidth );
CHECKF( usY >= 0 );
CHECKF( usY < usDestHeight );
CHECKF( srcRect->iRight > srcRect->iLeft );
CHECKF( srcRect->iBottom > srcRect->iTop );
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "End check" );
p16BPPPalette = hImage->pui16BPPPalette;
// determine where to start Copying and rectangle size
uiDestStart = usY * usDestWidth + usX;
uiNumLines = srcRect->iBottom - srcRect->iTop;
uiLineSize = srcRect->iRight - srcRect->iLeft;
Assert( usDestWidth >= uiLineSize );
Assert( usDestHeight >= uiNumLines );
pDest = (UINT16 *) pDestBuf;
pDest += uiDestStart;
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) );
// Copying a portion of a compressed image is rather messy
// because we have to decompress past all the data we want
// to skip.
// To keep memory requirements small and regular, we will
// decompress one scanline at a time even if none of the data will
// be blitted (but stop when the bottom line of the rectangle
// to blit has been done).
// initialize the decompression routines
pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight );
CHECKF( pDecompPtr );
// Allocate memory for one scanline
pScanLine = MemAlloc( hImage->usWidth );
CHECKF( pScanLine );
// go past all the scanlines we don't need to process
for (uiLine = 0; uiLine < (UINT32) srcRect->iTop; uiLine++)
{
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Skipping scanline" );
uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
Assert( uiDecompressed == hImage->usWidth );
}
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Actually Copying" );
// now we start Copying
for (uiLine = 0; uiLine < uiNumLines - 1; uiLine++)
{
// decompress a scanline
uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
Assert( uiDecompressed == hImage->usWidth );
// set pointers and blit
pDestTemp = pDest;
pScanLineTemp = pScanLine + srcRect->iLeft;
for (uiCol = 0; uiCol < uiLineSize; uiCol++ )
{
*pDestTemp = p16BPPPalette[ *pScanLineTemp ];
pDestTemp++;
pScanLineTemp++;
}
pDest += usDestWidth;
}
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) );
DecompressFini( pDecompPtr );
return( TRUE );
}
BOOLEAN Copy16BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
// 16BPP Compressed image has not been implemented yet
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "16BPP Compressed imagery blitter has not been implemented yet." );
return( FALSE );
}
#endif //NO_ZLIB_COMPRESSION
BOOLEAN Copy8BPPImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
UINT32 cnt;
UINT8 *pDest, *pSrc;
// Assertions
Assert( hImage != NULL );
Assert( hImage->p16BPPData != NULL );
// Validations
CHECKF( usX >= 0 );
CHECKF( usX < usDestWidth );
CHECKF( usY >= 0 );
CHECKF( usY < usDestHeight );
CHECKF( srcRect->iRight > srcRect->iLeft );
CHECKF( srcRect->iBottom > srcRect->iTop );
// Determine memcopy coordinates
uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
uiDestStart = usY * usDestWidth + usX;
uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1;
uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1;
Assert( usDestWidth >= uiLineSize );
Assert( usDestHeight >= uiNumLines );
// Copy line by line
pDest = ( UINT8*)pDestBuf + uiDestStart;
pSrc = hImage->p8BPPData + uiSrcStart;
for( cnt = 0; cnt < uiNumLines-1; cnt++ )
{
memcpy( pDest, pSrc, uiLineSize );
pDest += usDestWidth;
pSrc += hImage->usWidth;
}
// Do last line
memcpy( pDest, pSrc, uiLineSize );
return( TRUE );
}
BOOLEAN Copy16BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
UINT32 cnt;
UINT16 *pDest, *pSrc;
Assert( hImage != NULL );
Assert( hImage->p16BPPData != NULL );
// Validations
CHECKF( usX >= 0 );
CHECKF( usX < hImage->usWidth );
CHECKF( usY >= 0 );
CHECKF( usY < hImage->usHeight );
CHECKF( srcRect->iRight > srcRect->iLeft );
CHECKF( srcRect->iBottom > srcRect->iTop );
// Determine memcopy coordinates
uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
uiDestStart = usY * usDestWidth + usX;
uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1;
uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1;
CHECKF( usDestWidth >= uiLineSize );
CHECKF( usDestHeight >= uiNumLines );
// Copy line by line
pDest = ( UINT16*)pDestBuf + uiDestStart;
pSrc = hImage->p16BPPData + uiSrcStart;
for( cnt = 0; cnt < uiNumLines-1; cnt++ )
{
memcpy( pDest, pSrc, uiLineSize * 2 );
pDest += usDestWidth;
pSrc += hImage->usWidth;
}
// Do last line
memcpy( pDest, pSrc, uiLineSize * 2 );
return( TRUE );
}
BOOLEAN Extract8BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf )
{
return( FALSE );
}
BOOLEAN Extract16BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf )
{
return( FALSE );
}
BOOLEAN Copy8BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
{
UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
UINT32 rows, cols;
UINT8 *pSrc, *pSrcTemp;
UINT16 *pDest, *pDestTemp;
UINT16 *p16BPPPalette;
p16BPPPalette = hImage->pui16BPPPalette;
// Assertions
Assert( p16BPPPalette != NULL );
Assert( hImage != NULL );
// Validations
CHECKF( hImage->p16BPPData != NULL );
CHECKF( usX >= 0 );
CHECKF( usX < usDestWidth );
CHECKF( usY >= 0 );
CHECKF( usY < usDestHeight );
CHECKF( srcRect->iRight > srcRect->iLeft );
CHECKF( srcRect->iBottom > srcRect->iTop );
// Determine memcopy coordinates
uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
uiDestStart = usY * usDestWidth + usX;
uiNumLines = ( srcRect->iBottom - srcRect->iTop );
uiLineSize = ( srcRect->iRight - srcRect->iLeft );
CHECKF( usDestWidth >= uiLineSize );
CHECKF( usDestHeight >= uiNumLines );
// Convert to Pixel specification
pDest = ( UINT16*)pDestBuf + uiDestStart;
pSrc = hImage->p8BPPData + uiSrcStart;
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) );
// For every entry, look up into 16BPP palette
for( rows = 0; rows < uiNumLines-1; rows++ )
{
pDestTemp = pDest;
pSrcTemp = pSrc;
for ( cols = 0; cols < uiLineSize; cols++ )
{
*pDestTemp = p16BPPPalette[ *pSrcTemp ];
pDestTemp++;
pSrcTemp++;
}
pDest += usDestWidth;
pSrc += hImage->usWidth;
}
// Do last line
DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) );
return( TRUE );
}
UINT16 *Create16BPPPalette( SGPPaletteEntry *pPalette )
{
UINT16 *p16BPPPalette, r16, g16, b16, usColor;
UINT32 cnt;
UINT8 r,g,b;
Assert( pPalette != NULL );
p16BPPPalette = (UINT16 *) MemAlloc( sizeof( UINT16 ) * 256 );
for ( cnt = 0; cnt < 256; cnt++ )
{
r = pPalette[ cnt ].peRed;
g = pPalette[ cnt ].peGreen;
b = pPalette[ cnt ].peBlue;
if(gusRedShift < 0)
r16=((UINT16)r>>abs(gusRedShift));
else
r16=((UINT16)r<<gusRedShift);
if(gusGreenShift < 0)
g16=((UINT16)g>>abs(gusGreenShift));
else
g16=((UINT16)g<<gusGreenShift);
if(gusBlueShift < 0)
b16=((UINT16)b>>abs(gusBlueShift));
else
b16=((UINT16)b<<gusBlueShift);
usColor = (r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
if(usColor==0)
{
if((r+g+b)!=0)
usColor=BLACK_SUBSTITUTE | gusAlphaMask;
}
else
usColor |= gusAlphaMask;
p16BPPPalette[ cnt ] = usColor;
}
return( p16BPPPalette );
}
/**********************************************************************************************
Create16BPPPaletteShaded
Creates an 8 bit to 16 bit palette table, and modifies the colors as it builds.
Parameters:
rscale, gscale, bscale:
Color mode: Percentages (255=100%) of color to translate into destination palette.
Mono mode: Color for monochrome palette.
mono:
TRUE or FALSE to create a monochrome palette. In mono mode, Luminance values for
colors are calculated, and the RGB color is shaded according to each pixel's brightness.
This can be used in several ways:
1) To "brighten" a palette, pass down RGB values that are higher than 100% ( > 255) for all
three. mono=FALSE.
2) To "darken" a palette, do the same with less than 100% ( < 255) values. mono=FALSE.
3) To create a "glow" palette, select mono=TRUE, and pass the color in the RGB parameters.
4) For gamma correction, pass in weighted values for each color.
**********************************************************************************************/
UINT16 *Create16BPPPaletteShaded( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, UINT32 bscale, BOOLEAN mono)
{
UINT16 *p16BPPPalette, r16, g16, b16, usColor;
UINT32 cnt, lumin;
UINT32 rmod, gmod, bmod;
UINT8 r,g,b;
Assert( pPalette != NULL );
p16BPPPalette = (UINT16 *) MemAlloc( sizeof( UINT16 ) * 256 );
for ( cnt = 0; cnt < 256; cnt++ )
{
if(mono)
{
lumin=(pPalette[ cnt ].peRed*299/1000)+ (pPalette[ cnt ].peGreen*587/1000)+(pPalette[ cnt ].peBlue*114/1000);
rmod=(rscale*lumin)/256;
gmod=(gscale*lumin)/256;
bmod=(bscale*lumin)/256;
}
else
{
rmod = (rscale*pPalette[ cnt ].peRed/256);
gmod = (gscale*pPalette[ cnt ].peGreen/256);
bmod = (bscale*pPalette[ cnt ].peBlue/256);
}
r = (UINT8)__min(rmod, 255);
g = (UINT8)__min(gmod, 255);
b = (UINT8)__min(bmod, 255);
if(gusRedShift < 0)
r16=((UINT16)r>>(-gusRedShift));
else
r16=((UINT16)r<<gusRedShift);
if(gusGreenShift < 0)
g16=((UINT16)g>>(-gusGreenShift));
else
g16=((UINT16)g<<gusGreenShift);
if(gusBlueShift < 0)
b16=((UINT16)b>>(-gusBlueShift));
else
b16=((UINT16)b<<gusBlueShift);
// Prevent creation of pure black color
usColor = (r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
if(usColor==0)
{
if((r+g+b)!=0)
usColor=BLACK_SUBSTITUTE | gusAlphaMask;
}
else
usColor |= gusAlphaMask;
p16BPPPalette[ cnt ] = usColor;
}
return( p16BPPPalette );
}
// Convert from RGB to 16 bit value
UINT16 Get16BPPColor( UINT32 RGBValue )
{
UINT16 r16, g16, b16, usColor;
UINT8 r,g,b;
r = SGPGetRValue( RGBValue );
g = SGPGetGValue( RGBValue );
b = SGPGetBValue( RGBValue );
if(gusRedShift < 0)
r16=((UINT16)r>>abs(gusRedShift));
else
r16=((UINT16)r<<gusRedShift);
if(gusGreenShift < 0)
g16=((UINT16)g>>abs(gusGreenShift));
else
g16=((UINT16)g<<gusGreenShift);
if(gusBlueShift < 0)
b16=((UINT16)b>>abs(gusBlueShift));
else
b16=((UINT16)b<<gusBlueShift);
usColor=(r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
// if our color worked out to absolute black, and the original wasn't
// absolute black, convert it to a VERY dark grey to avoid transparency
// problems
if(usColor==0)
{
if(RGBValue!=0)
usColor=BLACK_SUBSTITUTE | gusAlphaMask;
}
else
usColor |= gusAlphaMask;
return(usColor);
}
// Convert from 16 BPP to RGBvalue
UINT32 GetRGBColor( UINT16 Value16BPP )
{
UINT16 r16, g16, b16;
UINT32 r,g,b,val;
r16 = Value16BPP & gusRedMask;
g16 = Value16BPP & gusGreenMask;
b16 = Value16BPP & gusBlueMask;
if(gusRedShift < 0)
r=((UINT32)r16<<abs(gusRedShift));
else
r=((UINT32)r16>>gusRedShift);
if(gusGreenShift < 0)
g=((UINT32)g16<<abs(gusGreenShift));
else
g=((UINT32)g16>>gusGreenShift);
if(gusBlueShift < 0)
b=((UINT32)b16<<abs(gusBlueShift));
else
b=((UINT32)b16>>gusBlueShift);
r &= 0x000000ff;
g &= 0x000000ff;
b &= 0x000000ff;
val = FROMRGB(r,g,b);
return(val);
}
//*****************************************************************************
//
// ConvertToPaletteEntry
//
// Parameter List : Converts from RGB to SGPPaletteEntry
//
// Return Value pointer to the SGPPaletteEntry
//
// Modification History :
// Dec 15th 1996 -> modified for use by Wizardry
//
//*****************************************************************************
SGPPaletteEntry *ConvertRGBToPaletteEntry(UINT8 sbStart, UINT8 sbEnd, UINT8 *pOldPalette)
{
UINT16 Index;
SGPPaletteEntry *pPalEntry;
SGPPaletteEntry *pInitEntry;
pPalEntry = (SGPPaletteEntry *)MemAlloc(sizeof(SGPPaletteEntry) * 256);
pInitEntry = pPalEntry;
DbgMessage(TOPIC_HIMAGE, DBG_LEVEL_0, "Converting RGB palette to SGPPaletteEntry");
for(Index=0; Index <= (sbEnd-sbStart);Index++)
{
pPalEntry->peRed = *(pOldPalette + (Index*3));
pPalEntry->peGreen = *(pOldPalette + (Index*3) + 1);
pPalEntry->peBlue = *(pOldPalette + (Index*3) + 2);
pPalEntry->peFlags = 0;
pPalEntry++;
}
return pInitEntry;
}
BOOLEAN GetETRLEImageData( HIMAGE hImage, ETRLEData *pBuffer )
{
// Assertions
Assert( hImage != NULL );
Assert( pBuffer != NULL );
// Create memory for data
pBuffer->usNumberOfObjects = hImage->usNumberOfObjects;
// Create buffer for objects
pBuffer->pETRLEObject = (ETRLEObject *) MemAlloc( sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects );
CHECKF( pBuffer->pETRLEObject != NULL );
// Copy into buffer
memcpy( pBuffer->pETRLEObject, hImage->pETRLEObject, sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects );
// Allocate memory for pixel data
pBuffer->pPixData = MemAlloc( hImage->uiSizePixData );
CHECKF( pBuffer->pPixData != NULL );
pBuffer->uiSizePixData = hImage->uiSizePixData;
// Copy into buffer
memcpy( pBuffer->pPixData, hImage->pPixData8, pBuffer->uiSizePixData );
return( TRUE );
}
void ConvertRGBDistribution565To555( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// If the pixel is completely black, don't bother converting it -- DB
if(*pPixel!=0)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// now shift back into the upper word
Pixel.uiValue <<= 5;
// and copy back
*pPixel = Pixel.usHigher | gusAlphaMask;
}
pPixel++;
}
}
void ConvertRGBDistribution565To655( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// shift to the right some more...
Pixel.uiValue >>= 5;
// so we can left-shift the red value alone to give it an extra bit
Pixel.usHigher <<= 1;
// now shift back and copy
Pixel.uiValue <<= 10;
*pPixel = Pixel.usHigher;
pPixel++;
}
}
void ConvertRGBDistribution565To556( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiLoop;
SplitUINT32 Pixel;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
// right shift the blue value (at the bottom) into the LOWER word to protect it
Pixel.usHigher = *pPixel;
Pixel.uiValue >>= 5;
// get rid of the least significant bit of green
Pixel.usHigher >>= 1;
// shift back into the upper word
Pixel.uiValue <<= 5;
// give blue an extra bit (blank in the least significant spot)
Pixel.usHigher <<= 1;
// copy back
*pPixel = Pixel.usHigher;
pPixel++;
}
}
void ConvertRGBDistribution565ToAny( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
{
UINT16 * pPixel;
UINT32 uiRed, uiGreen, uiBlue, uiTemp, uiLoop;
pPixel = p16BPPData;
for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
{
// put the 565 RGB 16-bit value into a 32-bit RGB value
uiRed = (*pPixel) >> 11;
uiGreen = (*pPixel & 0x07E0) >> 5;
uiBlue = (*pPixel & 0x001F);
uiTemp = FROMRGB(uiRed,uiGreen,uiBlue);
// then convert the 32-bit RGB value to whatever 16 bit format is used
*pPixel = Get16BPPColor( uiTemp );
pPixel++;
}
}