mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
Development Trunk (now obsolete): https://ja2svn.dyndns.org/source/ja2/branches/Wanne/JA2%201.13%20MP A detailed list of all the features (changes) is visible in the history log of the development trunk: INFO: There will be no further development in the development source trunk, so is obsolete from now on! This commit contains the following features (bugfixes are not listed): - New Feature: Show merc ranks in Strategy Screen before merc name o Toggle on/off in the ingame options screen o For each experience level (0-10) there are defined rank names in the language specific text files o Additional language text that is not translated yet is marked with // TODO.Translate - New Feature: Faster Bobby Ray Shipments o This feature is selectable in the ja2_options.ini o When activated Bobby Ray shipments will be really fast -> Overnight Express: 5 - 7 hours -> Air Service: 10, 12 or 14 hours -> Standard Service: 15, 18 or 21 hours o In a multiplayer game, this feature is disabled (because shipment arrive immediately in the destination sector) - New Feature: AP cost for manipulating the merc inventory o This feature is selectable in the start new game screen o For example, putting a weapon from hand in the backpack costs APs o The AP costs are defined in the APBPConstants.ini o In a multiplayer game, this feature is disabled - New Feature: Added possibility to set individual Gear Kit names o Set individual names in the optional new tag <mGearKitName> inside the <GEARKIT> root element (File: TableData\MercStartingGear.xml) - New Feature: Externalized the maximum purchase amount (JA2 vanilla: 10) for Bobby Rays purchases per shipment o Define the max. amount in the ja2_options.ini: BOBBY_RAY_MAX_PURCHASE_AMOUNT, Range: 10 - 100) o Nice scrolling bars to scroll through all the purchases - New Feature: Now it is possible to walk on "water" tiles or handle those tiles like "normal" tiles o (instead of showing the swimming animation and counting the APs for swimming), when the soldier is located on the second level (level > 0) - New Feature: Externalized AIM Veterans laptop site o Add maximum of 4 pages o Add new AIM to veterans page, and remove AIM from veterans page. o New XML file: OldAIMArchive.xml (language specific XML files: *.OldAIMArchive.xml) - New Feature: Added possibility to choose from 254 IMP faces o Modified IMPPortraits.xml o Added new GameDir folder "IMPFaces" which contains the IMP face portraits o Moved IMP faces in the new "IMPFaces" folder - New Feature: ARSP - All Resolution Support Project o See here: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=298698&page=1 o Support any kind of screen resolution. This works by choosing the matching full supported resolution (640x480, 800x600, 1024x768) and then centering the graphics o See ja2.ini for defining the screen resolution - New Feature: AI Turn Speed Up (FF-MOD) o see here: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=298699#Post298699 o When this feature is activated it allows fast enemy turns o New entry in ja2.ini to enable this feature: HIGHSPEED_TIMER = TRUE o Turn on/off auto fast turns in ingame options o New ja2_options.ini settings for fine tuning: [Clock Settings] ini block - New Feature: "Lock" / "Release" mouse cursor in tactical windowed mode, so the mouse can stay within window boundary o This is very helpful for doing scrolling with the mouse (by moving the mouse to the window edge) in windowed mode o You can toggle on/off the feature by pressing CTRL + Z. It is also possible to press CTRL + Y. So the user can decide which fits better :) o Whenever you toggle on/off a screen message appears on the tactical log to notify the player - New Feature: Weapon overheating o Basically, every shot fired from a gun increases its temperature. On higher temperatures, the gun jams more frequently o On/off toggle in the ingame options o Graphical thermometer indication on the weapon picture o New ja2_options.ini section with a few options, Section: [Tactical Weapon Overheating Settings] o XML changes (New Tags) --> AmmoTypes.xml: <temperatureModificator> --> Items.xml: <barrel>, <usOverheatingCooldownFactor> --> Weapons.xml: <usOverheatingJamThreshold>, <usOverheatingDamageThreshold>, <usOverheatingSingleShotTemperature> o Added a few barells to Items.xml (end of the file) o more infos: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=301059&page=1 - New Feature: Resting weapons on a surfaces o You can now rest your weapon on crates, low walls, rocks, debris, open windows etc. while you are crouched. Resting will give yu the superior gun handling modifiers from PRONE position. o A little 'A' on your gun indicates if you are resting it or not. o Both settings can be turned on and off in Ja2_Options.ini under 'Tactical Gameplay Settings' - New Feature: Externalized option on whether mercs can exit sector using grid exit in turn based mode o new ja2_options.ini property: GRID_EXIT_IN_TURNBASED o This ini setting does not affect leaving sectors on map edges - Rework/Update: Ammo boxes and Ammo crates o Ammo crate items added for remaining calibers. Tweaked prices to correspond to magazines, tweaked capacities and weights to be reasonable (~800 or less). o Shift-R reload now looks at both boxes and crates in sector items and merc's inventory to reload, and tops off magazines in inventory as well. Only possible outside of combat. o Ctrl-Shift-A still creates crates as per usual, with some fixes to ensure all ammo is caught on the first press. o Shift-A now creates ammo boxes in the same loop. They mostly behave like crates, but fit in mercs inventories. o Ammo boxes are available to purchase at BR and tony, sam, etc. Individual magazines/drums/etc are no longer available. o Removed ammo crate xml tag. Added ubMagType tag to Magazines array. This allows us to differentiate between magazines, bullets, boxes and crates. o Changed ammo filtering in BR's to display boxes appropriately. Added back the "Mag:" display (changed text to "Size:") o Added ja2set.dat.xml file (WF map version in WF maps folder) to be used instead of ja2set.dat file (ja2.ini setting added) For now, if you want to play vanilla instead, just change the setting in the ini (see comments in file). o Added P4-P9Items image files (up to 5k images each) and tileslots. 1.13 core items will continue to use Guns and P1-P3Items for the foreseeable future. P4-P9 can be used by customizers/modders to avoid conflicts with Guns/P1-P3 items. TODO: Need to discuss a strategy for this in the forums. o Added in Ambient/0.bad and 32.bad to avoid an exception in the code. o Updated the XML Editor o Standardized the text on all the ammo items. - New Multiplayer Feature: Sharing same FOV (field of view) in a coop/team-dm (for friendly teams) game o You will also see enemies, that your teammate sees git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5108 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1748 lines
49 KiB
C++
1748 lines
49 KiB
C++
#ifdef JA2_PRECOMPILED_HEADERS
|
|
#include "JA2 SGP ALL.H"
|
|
#elif defined( WIZ8_PRECOMPILED_HEADERS )
|
|
#include "WIZ8 SGP ALL.H"
|
|
#else
|
|
#include "DirectDraw Calls.h"
|
|
#include <stdio.h>
|
|
#include "debug.h"
|
|
#if defined( JA2 ) || defined( UTIL )
|
|
#include "video.h"
|
|
#else
|
|
#include "video2.h"
|
|
#endif
|
|
#include "himage.h"
|
|
#include "vobject.h"
|
|
#include "vobject_private.h"
|
|
#include "video_private.h"
|
|
#include "wcheck.h"
|
|
#include "vobject_blitters.h"
|
|
#include "sgp.h"
|
|
#endif
|
|
|
|
// ******************************************************************************
|
|
//
|
|
// Video Object SGP Module
|
|
//
|
|
// Video Objects are used to contain any imagery which requires blitting. The data
|
|
// is contained within a Direct Draw surface. Palette information is in both
|
|
// a Direct Draw Palette and a 16BPP palette structure for 8->16 BPP Blits.
|
|
// Blitting is done via Direct Draw as well as custum blitters. Regions are
|
|
// used to define local coordinates within the surface
|
|
//
|
|
// Second Revision: Dec 10, 1996, Andrew Emmons
|
|
//
|
|
// *******************************************************************************
|
|
|
|
|
|
// *******************************************************************************
|
|
// Defines
|
|
// *******************************************************************************
|
|
|
|
// This define is sent to CreateList SGP function. It dynamically re-sizes if
|
|
// the list gets larger
|
|
#define DEFAULT_VIDEO_OBJECT_LIST_SIZE 10
|
|
|
|
#define COMPRESS_TRANSPARENT 0x80
|
|
#define COMPRESS_RUN_MASK 0x7F
|
|
|
|
// *******************************************************************************
|
|
// External Functions and variables
|
|
// *******************************************************************************
|
|
|
|
// *******************************************************************************
|
|
// LOCAL functions
|
|
// *******************************************************************************
|
|
|
|
|
|
// *******************************************************************************
|
|
// LOCAL global variables
|
|
// *******************************************************************************
|
|
|
|
|
|
|
|
HLIST ghVideoObjects = NULL;
|
|
BOOLEAN gfVideoObjectsInit=FALSE;
|
|
|
|
typedef struct VOBJECT_NODE
|
|
{
|
|
HVOBJECT hVObject;
|
|
UINT32 uiIndex;
|
|
struct VOBJECT_NODE *next, *prev;
|
|
|
|
#ifdef SGP_VIDEO_DEBUGGING
|
|
STR8 pName;
|
|
STR8 pCode;
|
|
#endif
|
|
|
|
}VOBJECT_NODE;
|
|
|
|
VOBJECT_NODE *gpVObjectHead = NULL;
|
|
VOBJECT_NODE *gpVObjectTail = NULL;
|
|
UINT32 guiVObjectIndex = 1;
|
|
UINT32 guiVObjectSize = 0;
|
|
UINT32 guiVObjectTotalAdded = 0;
|
|
|
|
#ifdef _DEBUG
|
|
enum
|
|
{
|
|
DEBUGSTR_NONE,
|
|
DEBUGSTR_SETVIDEOOBJECTTRANSPARENCY,
|
|
DEBUGSTR_BLTVIDEOOBJECTFROMINDEX,
|
|
DEBUGSTR_SETOBJECTHANDLESHADE,
|
|
DEBUGSTR_GETVIDEOOBJECTETRLESUBREGIONPROPERTIES,
|
|
DEBUGSTR_GETVIDEOOBJECTETRLEPROPERTIESFROMINDEX,
|
|
DEBUGSTR_SETVIDEOOBJECTPALETTE8BPP,
|
|
DEBUGSTR_GETVIDEOOBJECTPALETTE16BPP,
|
|
DEBUGSTR_COPYVIDEOOBJECTPALETTE16BPP,
|
|
DEBUGSTR_BLTVIDEOOBJECTOUTLINEFROMINDEX,
|
|
DEBUGSTR_BLTVIDEOOBJECTOUTLINESHADOWFROMINDEX,
|
|
DEBUGSTR_DELETEVIDEOOBJECTFROMINDEX
|
|
};
|
|
|
|
UINT8 gubVODebugCode = 0;
|
|
|
|
void CheckValidVObjectIndex( UINT32 uiIndex );
|
|
#endif
|
|
|
|
// **************************************************************
|
|
//
|
|
// Video Object Manager functions
|
|
//
|
|
// **************************************************************
|
|
|
|
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
|
|
{
|
|
puts("in filter.");
|
|
if (code == EXCEPTION_ACCESS_VIOLATION) {
|
|
puts("caught AV as expected.");
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
else
|
|
{
|
|
puts("didn't catch AV, unexpected.");
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
};
|
|
}
|
|
|
|
BOOLEAN InitializeVideoObjectManager( )
|
|
{
|
|
//Shouldn't be calling this if the video object manager already exists.
|
|
//Call shutdown first...
|
|
Assert( !gpVObjectHead );
|
|
Assert( !gpVObjectTail );
|
|
RegisterDebugTopic(TOPIC_VIDEOOBJECT, "Video Object Manager");
|
|
gpVObjectHead = gpVObjectTail = NULL;
|
|
gfVideoObjectsInit=TRUE;
|
|
return TRUE ;
|
|
}
|
|
|
|
BOOLEAN ShutdownVideoObjectManager( )
|
|
{
|
|
VOBJECT_NODE *curr;
|
|
while( gpVObjectHead )
|
|
{
|
|
curr = gpVObjectHead;
|
|
gpVObjectHead = gpVObjectHead->next;
|
|
DeleteVideoObject( curr->hVObject );
|
|
#ifdef SGP_VIDEO_DEBUGGING
|
|
if( curr->pName )
|
|
MemFree( curr->pName );
|
|
if( curr->pCode )
|
|
MemFree( curr->pCode );
|
|
#endif
|
|
MemFree( curr );
|
|
}
|
|
gpVObjectHead = NULL;
|
|
gpVObjectTail = NULL;
|
|
guiVObjectIndex = 1;
|
|
guiVObjectSize = 0;
|
|
guiVObjectTotalAdded = 0;
|
|
UnRegisterDebugTopic(TOPIC_VIDEOOBJECT, "Video Objects");
|
|
gfVideoObjectsInit=FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
UINT32 CountVideoObjectNodes()
|
|
{
|
|
VOBJECT_NODE *curr;
|
|
UINT32 i = 0;
|
|
curr = gpVObjectHead;
|
|
while( curr )
|
|
{
|
|
i++;
|
|
curr = curr->next;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
BOOLEAN AddStandardVideoObject( VOBJECT_DESC *pVObjectDesc, UINT32 *puiIndex )
|
|
{
|
|
|
|
HVOBJECT hVObject;
|
|
|
|
// Assertions
|
|
Assert( puiIndex );
|
|
Assert( pVObjectDesc );
|
|
|
|
// Create video object
|
|
hVObject = CreateVideoObject( pVObjectDesc );
|
|
|
|
if( !hVObject )
|
|
{
|
|
// Video Object will set error condition.
|
|
return FALSE ;
|
|
}
|
|
|
|
// Set transparency to default
|
|
SetVideoObjectTransparencyColor( hVObject, FROMRGB( 0, 0, 0 ) );
|
|
|
|
// Set into video object list
|
|
if( gpVObjectHead )
|
|
{ //Add node after tail
|
|
gpVObjectTail->next = (VOBJECT_NODE*)MemAlloc( sizeof( VOBJECT_NODE ) );
|
|
Assert( gpVObjectTail->next ); //out of memory?
|
|
gpVObjectTail->next->prev = gpVObjectTail;
|
|
gpVObjectTail->next->next = NULL;
|
|
gpVObjectTail = gpVObjectTail->next;
|
|
}
|
|
else
|
|
{ //new list
|
|
gpVObjectHead = (VOBJECT_NODE*)MemAlloc( sizeof( VOBJECT_NODE ) );
|
|
Assert( gpVObjectHead ); //out of memory?
|
|
gpVObjectHead->prev = gpVObjectHead->next = NULL;
|
|
gpVObjectTail = gpVObjectHead;
|
|
}
|
|
#ifdef SGP_VIDEO_DEBUGGING
|
|
gpVObjectTail->pName = NULL;
|
|
gpVObjectTail->pCode = NULL;
|
|
#endif
|
|
//Set the hVObject into the node.
|
|
gpVObjectTail->hVObject = hVObject;
|
|
gpVObjectTail->uiIndex = guiVObjectIndex+=2;
|
|
*puiIndex = gpVObjectTail->uiIndex;
|
|
Assert( guiVObjectIndex < 0xfffffff0 ); //unlikely that we will ever use 2 billion vobjects!
|
|
//We would have to create about 70 vobjects per second for 1 year straight to achieve this...
|
|
guiVObjectSize++;
|
|
guiVObjectTotalAdded++;
|
|
|
|
#ifdef JA2TESTVERSION
|
|
if( CountVideoObjectNodes() != guiVObjectSize )
|
|
{
|
|
guiVObjectSize = guiVObjectSize;
|
|
}
|
|
#endif
|
|
|
|
return TRUE ;
|
|
}
|
|
|
|
|
|
BOOLEAN SetVideoObjectTransparency( UINT32 uiIndex, COLORVAL TransColor )
|
|
{
|
|
HVOBJECT hVObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_SETVIDEOOBJECTTRANSPARENCY;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiIndex ) );
|
|
|
|
// Set transparency
|
|
SetVideoObjectTransparencyColor( hVObject, TransColor );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN GetVideoObject( HVOBJECT *hVObject, UINT32 uiIndex )
|
|
{
|
|
VOBJECT_NODE *curr;
|
|
|
|
#ifdef _DEBUG
|
|
CheckValidVObjectIndex( uiIndex );
|
|
#endif
|
|
|
|
curr = gpVObjectHead;
|
|
while( curr )
|
|
{
|
|
if( curr->uiIndex == uiIndex )
|
|
{
|
|
*hVObject = curr->hVObject;
|
|
return TRUE;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
*hVObject = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN BltVideoObjectFromIndex(UINT32 uiDestVSurface, UINT32 uiSrcVObject, UINT16 usRegionIndex, INT32 iDestX, INT32 iDestY, UINT32 fBltFlags, blt_fx *pBltFx )
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
HVOBJECT hSrcVObject;
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_BLTVIDEOOBJECTFROMINDEX;
|
|
#endif
|
|
if( !GetVideoObject( &hSrcVObject, uiSrcVObject ) )
|
|
{
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return FALSE;
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
if ( !BltVideoObjectToBuffer( pBuffer, uiPitch, hSrcVObject, usRegionIndex, iDestX, iDestY, fBltFlags, pBltFx ) )
|
|
{
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
// VO Blitter will set debug messages for error conditions
|
|
return FALSE;
|
|
}
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN DeleteVideoObjectFromIndex( UINT32 uiVObject )
|
|
{
|
|
VOBJECT_NODE *curr;
|
|
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_DELETEVIDEOOBJECTFROMINDEX;
|
|
CheckValidVObjectIndex( uiVObject );
|
|
#endif
|
|
|
|
curr = gpVObjectHead;
|
|
while( curr )
|
|
{
|
|
if( curr->uiIndex == uiVObject )
|
|
{ //Found the node, so detach it and delete it.
|
|
|
|
//Deallocate the memory for the video object
|
|
DeleteVideoObject( curr->hVObject );
|
|
|
|
if( curr == gpVObjectHead )
|
|
{ //Advance the head, because we are going to remove the head node.
|
|
gpVObjectHead = gpVObjectHead->next;
|
|
}
|
|
if( curr == gpVObjectTail )
|
|
{ //Back up the tail, because we are going to remove the tail node.
|
|
gpVObjectTail = gpVObjectTail->prev;
|
|
}
|
|
//Detach the node from the vobject list
|
|
if( curr->next )
|
|
{ //Make the prev node point to the next
|
|
curr->next->prev = curr->prev;
|
|
}
|
|
if( curr->prev )
|
|
{ //Make the next node point to the prev
|
|
curr->prev->next = curr->next;
|
|
}
|
|
//The node is now detached. Now deallocate it.
|
|
#ifdef SGP_VIDEO_DEBUGGING
|
|
if( curr->pName )
|
|
MemFree( curr->pName );
|
|
if( curr->pCode )
|
|
MemFree( curr->pCode );
|
|
#endif
|
|
MemFree( curr );
|
|
curr = NULL;
|
|
guiVObjectSize--;
|
|
#ifdef JA2TESTVERSION
|
|
if( CountVideoObjectNodes() != guiVObjectSize )
|
|
{
|
|
guiVObjectSize = guiVObjectSize;
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// Given an index to the dest and src vobject contained in ghVideoObjects
|
|
// Based on flags, blit accordingly
|
|
// There are two types, a BltFast and a Blt. BltFast is 10% faster, uses no
|
|
// clipping lists
|
|
BOOLEAN BltVideoObject( UINT32 uiDestVSurface,
|
|
HVOBJECT hSrcVObject,
|
|
UINT16 usRegionIndex,
|
|
INT32 iDestX,
|
|
INT32 iDestY,
|
|
UINT32 fBltFlags,
|
|
blt_fx *pBltFx )
|
|
{
|
|
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
if ( !BltVideoObjectToBuffer( pBuffer, uiPitch, hSrcVObject, usRegionIndex, iDestX, iDestY, fBltFlags, pBltFx ) )
|
|
{
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
// VO Blitter will set debug messages for error conditions
|
|
return( FALSE );
|
|
}
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
// *******************************************************************************
|
|
// Video Object Manipulation Functions
|
|
// *******************************************************************************
|
|
|
|
|
|
HVOBJECT CreateVideoObject( VOBJECT_DESC *VObjectDesc )
|
|
{
|
|
HVOBJECT hVObject;
|
|
HIMAGE hImage;
|
|
ETRLEData TempETRLEData;
|
|
// UINT32 count;
|
|
|
|
// Allocate memory for video object data and initialize
|
|
hVObject = (HVOBJECT) MemAlloc( sizeof( SGPVObject ) );
|
|
CHECKF( hVObject != NULL );
|
|
memset( hVObject, 0, sizeof( SGPVObject ) );
|
|
|
|
// default of all members of the vobject is 0
|
|
|
|
// Check creation options
|
|
// do
|
|
// {
|
|
if ( VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMFILE || VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMHIMAGE )
|
|
{
|
|
if ( VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMFILE )
|
|
{
|
|
ImageFileType::TestOrder order = ImageFileType::JPC_FALLBACK;
|
|
|
|
if(VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMJPC) {
|
|
order = ImageFileType::JPC;
|
|
} else if(VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMJPC_FALLBACK) {
|
|
order = ImageFileType::JPC_FALLBACK;
|
|
} else if(VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMPNG) {
|
|
order = ImageFileType::PNG_FALLBACK;
|
|
} else if(VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMPNG_FALLBACK) {
|
|
order = ImageFileType::PNG_FALLBACK;
|
|
}
|
|
// Create himage object from file
|
|
hImage = CreateImage( VObjectDesc->ImageFile, IMAGE_ALLIMAGEDATA, order );
|
|
|
|
if ( hImage == NULL )
|
|
{
|
|
MemFree( hVObject );
|
|
DbgMessage( TOPIC_VIDEOOBJECT, DBG_LEVEL_2, "Invalid Image Filename given" );
|
|
return( NULL );
|
|
}
|
|
}
|
|
else
|
|
{ // create video object from provided hImage
|
|
hImage = VObjectDesc->hImage;
|
|
if ( hImage == NULL )
|
|
{
|
|
MemFree( hVObject );
|
|
DbgMessage( TOPIC_VIDEOOBJECT, DBG_LEVEL_2, "Invalid hImage pointer given" );
|
|
return( NULL );
|
|
}
|
|
}
|
|
|
|
if(hImage->ubBitDepth == 32)
|
|
{
|
|
SGP_THROW_IFFALSE(hImage->usNumberOfObjects > 0, L"bad himage");
|
|
|
|
// create one 16bpp object (that contains 32bpp data)
|
|
hVObject->p16BPPObject = (SixteenBPPObjectInfo*)MemAlloc(sizeof(SixteenBPPObjectInfo));
|
|
if(!hVObject->p16BPPObject)
|
|
{
|
|
SGP_THROW(L"bad alloc");
|
|
}
|
|
memset(hVObject->p16BPPObject, 0, sizeof(SixteenBPPObjectInfo));
|
|
|
|
int SIZE = hImage->pETRLEObject[0].usHeight * hImage->pETRLEObject[0].usWidth * sizeof(UINT32);
|
|
hVObject->p16BPPObject->p16BPPData = (UINT16*)MemAlloc(SIZE); // UINT32*
|
|
if(!hVObject->p16BPPObject->p16BPPData)
|
|
{
|
|
MemFree(hVObject->p16BPPObject);
|
|
SGP_THROW(L"bad alloc");
|
|
}
|
|
memcpy(hVObject->p16BPPObject->p16BPPData, hImage->p32BPPData, SIZE);
|
|
|
|
hVObject->p16BPPObject->sOffsetX = hImage->pETRLEObject[0].sOffsetX;
|
|
hVObject->p16BPPObject->sOffsetY = hImage->pETRLEObject[0].sOffsetY;
|
|
hVObject->p16BPPObject->ubShadeLevel = 0;
|
|
hVObject->p16BPPObject->usHeight = hImage->pETRLEObject[0].usHeight;
|
|
hVObject->p16BPPObject->usWidth = hImage->pETRLEObject[0].usWidth;
|
|
hVObject->p16BPPObject->usRegionIndex = 0;
|
|
|
|
hVObject->usNumberOf16BPPObjects = 1;
|
|
hVObject->ubBitDepth = hImage->ubBitDepth;
|
|
|
|
if ( VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMFILE )
|
|
{
|
|
DestroyImage( hImage );
|
|
}
|
|
|
|
return hVObject;
|
|
}
|
|
else if(hImage->ubBitDepth == 16)
|
|
{
|
|
SGP_THROW_IFFALSE(hImage->usNumberOfObjects > 0, L"bad himage");
|
|
|
|
// create one 16bpp object (that contains 32bpp data)
|
|
hVObject->p16BPPObject = (SixteenBPPObjectInfo*)MemAlloc(sizeof(SixteenBPPObjectInfo));
|
|
if(!hVObject->p16BPPObject)
|
|
{
|
|
SGP_THROW(L"bad alloc");
|
|
}
|
|
memset(hVObject->p16BPPObject, 0, sizeof(SixteenBPPObjectInfo));
|
|
|
|
int SIZE = hImage->pETRLEObject[0].usHeight * hImage->pETRLEObject[0].usWidth * sizeof(UINT16);
|
|
hVObject->p16BPPObject->p16BPPData = (UINT16*)MemAlloc(SIZE);
|
|
if(!hVObject->p16BPPObject->p16BPPData)
|
|
{
|
|
MemFree(hVObject->p16BPPObject);
|
|
SGP_THROW(L"bad alloc");
|
|
}
|
|
memcpy(hVObject->p16BPPObject->p16BPPData, hImage->p16BPPData, SIZE);
|
|
|
|
hVObject->p16BPPObject->sOffsetX = hImage->pETRLEObject[0].sOffsetX;
|
|
hVObject->p16BPPObject->sOffsetY = hImage->pETRLEObject[0].sOffsetY;
|
|
hVObject->p16BPPObject->ubShadeLevel = 0;
|
|
hVObject->p16BPPObject->usHeight = hImage->pETRLEObject[0].usHeight;
|
|
hVObject->p16BPPObject->usWidth = hImage->pETRLEObject[0].usWidth;
|
|
hVObject->p16BPPObject->usRegionIndex = 0;
|
|
|
|
hVObject->usNumberOf16BPPObjects = 1;
|
|
hVObject->ubBitDepth = hImage->ubBitDepth;
|
|
|
|
if ( VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMFILE )
|
|
{
|
|
DestroyImage( hImage );
|
|
}
|
|
|
|
return hVObject;
|
|
}
|
|
|
|
// Check if returned himage is TRLE compressed - return error if not
|
|
if ( ! (hImage->fFlags & IMAGE_TRLECOMPRESSED ) )
|
|
{
|
|
MemFree( hVObject );
|
|
DbgMessage( TOPIC_VIDEOOBJECT, DBG_LEVEL_2, "Invalid Image format given." );
|
|
DestroyImage( hImage );
|
|
return( NULL );
|
|
}
|
|
|
|
// Set values from himage
|
|
hVObject->ubBitDepth = hImage->ubBitDepth;
|
|
|
|
// Get TRLE data
|
|
CHECKF( GetETRLEImageData( hImage, &TempETRLEData ) );
|
|
|
|
// Set values
|
|
hVObject->usNumberOfObjects = TempETRLEData.usNumberOfObjects;
|
|
hVObject->pETRLEObject = TempETRLEData.pETRLEObject;
|
|
hVObject->pPixData = TempETRLEData.pPixData;
|
|
hVObject->uiSizePixData = TempETRLEData.uiSizePixData;
|
|
|
|
// Set palette from himage
|
|
if ( hImage->ubBitDepth == 8 )
|
|
{
|
|
hVObject->pShade8=ubColorTables[DEFAULT_SHADE_LEVEL];
|
|
hVObject->pGlow8=ubColorTables[0];
|
|
|
|
SetVideoObjectPalette( hVObject, hImage->pPalette );
|
|
|
|
}
|
|
|
|
if ( VObjectDesc->fCreateFlags & VOBJECT_CREATE_FROMFILE )
|
|
{
|
|
// Delete himage object
|
|
DestroyImage( hImage );
|
|
}
|
|
// break;
|
|
}
|
|
else
|
|
{
|
|
MemFree( hVObject );
|
|
DbgMessage( TOPIC_VIDEOOBJECT, DBG_LEVEL_2, "Invalid VObject creation flags given." );
|
|
return( NULL );
|
|
}
|
|
|
|
// If here, no special options given, use structure given in paraneters
|
|
// TO DO:
|
|
|
|
// }
|
|
// while( FALSE );
|
|
|
|
// All is well
|
|
// DbgMessage( TOPIC_VIDEOOBJECT, DBG_LEVEL_3, String("Success in Creating Video Object" ) );
|
|
|
|
return( hVObject );
|
|
}
|
|
|
|
|
|
// Palette setting is expensive, need to set both DDPalette and create 16BPP palette
|
|
BOOLEAN SetVideoObjectPalette( HVOBJECT hVObject, SGPPaletteEntry *pSrcPalette )
|
|
{
|
|
|
|
Assert( hVObject != NULL );
|
|
Assert( pSrcPalette != NULL );
|
|
|
|
// Create palette object if not already done so
|
|
if ( hVObject->pPaletteEntry == NULL )
|
|
{
|
|
// Create palette
|
|
hVObject->pPaletteEntry = (SGPPaletteEntry *) MemAlloc( sizeof( SGPPaletteEntry ) * 256 );
|
|
CHECKF( hVObject->pPaletteEntry != NULL );
|
|
|
|
// Copy src into palette
|
|
memcpy( hVObject->pPaletteEntry, pSrcPalette, sizeof( SGPPaletteEntry ) * 256 );
|
|
|
|
}
|
|
else
|
|
{
|
|
// Just Change entries
|
|
memcpy( hVObject->pPaletteEntry, pSrcPalette, sizeof( SGPPaletteEntry ) * 256 );
|
|
}
|
|
|
|
// Delete 16BPP Palette if one exists
|
|
if ( hVObject->p16BPPPalette != NULL )
|
|
{
|
|
MemFree( hVObject->p16BPPPalette );
|
|
hVObject->p16BPPPalette = NULL;
|
|
}
|
|
|
|
// Create 16BPP Palette
|
|
hVObject->p16BPPPalette = Create16BPPPalette( pSrcPalette );
|
|
hVObject->pShadeCurrent = hVObject->p16BPPPalette;
|
|
|
|
// DbgMessage(TOPIC_VIDEOOBJECT, DBG_LEVEL_3, String("Video Object Palette change successfull" ));
|
|
return( TRUE );
|
|
}
|
|
|
|
// Transparency needs to take RGB value and find best fit and place it into DD Surface
|
|
// colorkey value.
|
|
BOOLEAN SetVideoObjectTransparencyColor( HVOBJECT hVObject, COLORVAL TransColor )
|
|
{
|
|
|
|
// Assertions
|
|
Assert( hVObject != NULL );
|
|
|
|
//Set trans color into video object
|
|
hVObject->TransparentColor = TransColor;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
// Deletes all palettes, surfaces and region data
|
|
BOOLEAN DeleteVideoObject( HVOBJECT hVObject )
|
|
{
|
|
UINT16 usLoop;
|
|
|
|
// Assertions
|
|
CHECKF( hVObject != NULL );
|
|
|
|
DestroyObjectPaletteTables(hVObject);
|
|
|
|
// Release palette
|
|
if ( hVObject->pPaletteEntry != NULL )
|
|
{
|
|
MemFree( hVObject->pPaletteEntry );
|
|
// hVObject->pPaletteEntry = NULL;
|
|
}
|
|
|
|
|
|
if ( hVObject->pPixData != NULL )
|
|
{
|
|
MemFree( hVObject->pPixData );
|
|
// hVObject->pPixData = NULL;
|
|
}
|
|
|
|
if ( hVObject->pETRLEObject != NULL )
|
|
{
|
|
MemFree( hVObject->pETRLEObject );
|
|
// hVObject->pETRLEObject = NULL;
|
|
}
|
|
|
|
if ( hVObject->ppZStripInfo != NULL )
|
|
{
|
|
for (usLoop = 0; usLoop < hVObject->usNumberOfObjects; usLoop++)
|
|
{
|
|
if (hVObject->ppZStripInfo[usLoop] != NULL)
|
|
{
|
|
MemFree( hVObject->ppZStripInfo[usLoop]->pbZChange );
|
|
MemFree( hVObject->ppZStripInfo[usLoop] );
|
|
}
|
|
}
|
|
MemFree( hVObject->ppZStripInfo );
|
|
// hVObject->ppZStripInfo = NULL;
|
|
}
|
|
|
|
if ( hVObject->usNumberOf16BPPObjects > 0)
|
|
{
|
|
for( usLoop = 0; usLoop < hVObject->usNumberOf16BPPObjects; usLoop++)
|
|
{
|
|
MemFree( hVObject->p16BPPObject[usLoop].p16BPPData );
|
|
}
|
|
MemFree( hVObject->p16BPPObject );
|
|
}
|
|
|
|
// Release object
|
|
MemFree( hVObject );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
/**********************************************************************************************
|
|
CreateObjectPaletteTables
|
|
|
|
Creates the shading tables for 8-bit brushes. One highlight table is created, based on
|
|
the object-type, 3 brightening tables, 1 normal, and 11 darkening tables. The entries are
|
|
created iteratively, rather than in a loop to allow hand-tweaking of the values. If you
|
|
change the HVOBJECT_SHADE_TABLES symbol, remember to add/delete entries here, it won't
|
|
adjust automagically.
|
|
|
|
**********************************************************************************************/
|
|
|
|
UINT16 CreateObjectPaletteTables(HVOBJECT pObj, UINT32 uiType)
|
|
{
|
|
UINT32 count;
|
|
|
|
// this creates the highlight table. Specify the glow-type when creating the tables
|
|
// through uiType, symbols are from VOBJECT.H
|
|
for( count = 0; count < 16; count++ )
|
|
{
|
|
if ( (count == 4) && (pObj->p16BPPPalette == pObj->pShades[ count ]) )
|
|
pObj->pShades[ count ] = NULL;
|
|
else if ( pObj->pShades[ count ] != NULL )
|
|
{
|
|
MemFree( pObj->pShades[ count ] );
|
|
pObj->pShades[ count ] = NULL;
|
|
}
|
|
}
|
|
|
|
switch(uiType)
|
|
{
|
|
case HVOBJECT_GLOW_GREEN: // green glow
|
|
pObj->pShades[0]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 0, 255, 0, TRUE);
|
|
break;
|
|
case HVOBJECT_GLOW_BLUE: // blue glow
|
|
pObj->pShades[0]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 0, 0, 255, TRUE);
|
|
break;
|
|
case HVOBJECT_GLOW_YELLOW: // yellow glow
|
|
pObj->pShades[0]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 255, 255, 0, TRUE);
|
|
break;
|
|
case HVOBJECT_GLOW_RED: // red glow
|
|
pObj->pShades[0]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 255, 0, 0, TRUE);
|
|
break;
|
|
}
|
|
|
|
// these are the brightening tables, 115%-150% brighter than original
|
|
pObj->pShades[1]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 293, 293, 293, FALSE);
|
|
pObj->pShades[2]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 281, 281, 281, FALSE);
|
|
pObj->pShades[3]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 268, 268, 268, FALSE);
|
|
|
|
// palette 4 is the non-modified palette.
|
|
// if the standard one has already been made, we'll use it
|
|
if(pObj->p16BPPPalette!=NULL)
|
|
pObj->pShades[4]=pObj->p16BPPPalette;
|
|
else
|
|
{
|
|
// or create our own, and assign it to the standard one
|
|
pObj->pShades[4]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 255, 255, 255, FALSE);
|
|
pObj->p16BPPPalette=pObj->pShades[4];
|
|
}
|
|
|
|
// the rest are darkening tables, right down to all-black.
|
|
pObj->pShades[5]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 195, 195, 195, FALSE);
|
|
pObj->pShades[6]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 165, 165, 165, FALSE);
|
|
pObj->pShades[7]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 135, 135, 135, FALSE);
|
|
pObj->pShades[8]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 105, 105, 105, FALSE);
|
|
pObj->pShades[9]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 75, 75, 75, FALSE);
|
|
pObj->pShades[10]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 45, 45, 45, FALSE);
|
|
pObj->pShades[11]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 36, 36, 36, FALSE);
|
|
pObj->pShades[12]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 27, 27, 27, FALSE);
|
|
pObj->pShades[13]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 18, 18, 18, FALSE);
|
|
pObj->pShades[14]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 9, 9, 9, FALSE);
|
|
pObj->pShades[15]=Create16BPPPaletteShaded( pObj->pPaletteEntry, 0, 0, 0, FALSE);
|
|
|
|
// Set current shade table to neutral color
|
|
pObj->pShadeCurrent=pObj->pShades[4];
|
|
|
|
// check to make sure every table got a palette
|
|
for(count=0; (count < HVOBJECT_SHADE_TABLES) && (pObj->pShades[count]!=NULL); count++);
|
|
|
|
|
|
// return the result of the check
|
|
return(count==HVOBJECT_SHADE_TABLES);
|
|
}
|
|
|
|
// *******************************************************************
|
|
//
|
|
// Blitting Functions
|
|
//
|
|
// *******************************************************************
|
|
|
|
// High level blit function encapsolates ALL effects and BPP
|
|
BOOLEAN BltVideoObjectToBuffer( UINT16 *pBuffer, UINT32 uiDestPitchBYTES, HVOBJECT hSrcVObject, UINT16 usIndex, INT32 iDestX, INT32 iDestY, INT32 fBltFlags, blt_fx *pBltFx )
|
|
{
|
|
// Sometimes an exception is thrown in that method.
|
|
//BF __try
|
|
{
|
|
// Assertions
|
|
//Assert( pBuffer != NULL );
|
|
SGP_THROW_IFFALSE( pBuffer != NULL, L"No Destination Buffer" );
|
|
|
|
if ( hSrcVObject == NULL )
|
|
{
|
|
//int breakpoint=0;
|
|
}
|
|
|
|
//Assert( hSrcVObject != NULL );
|
|
SGP_THROW_IFFALSE( hSrcVObject != NULL, L"No Source Object" )
|
|
|
|
SixteenBPPObjectInfo *image = NULL;
|
|
// Check For Flags and bit depths
|
|
switch( hSrcVObject->ubBitDepth )
|
|
{
|
|
case 32:
|
|
SGP_THROW_IFFALSE(usIndex < hSrcVObject->usNumberOf16BPPObjects, L"index larger that number images");
|
|
image = &hSrcVObject->p16BPPObject[usIndex];
|
|
#if 0
|
|
Blt16BPPTo16BPPTrans( pBuffer, uiDestPitchBYTES,
|
|
image->p16BPPData, image->usWidth * sizeof(UINT16),
|
|
iDestX, iDestY,
|
|
0, 0, image->usWidth, image->usHeight,
|
|
0 );
|
|
#else
|
|
Blt32BPPTo16BPPTrans( pBuffer, uiDestPitchBYTES,
|
|
(UINT32*)image->p16BPPData, image->usWidth * sizeof(UINT32),
|
|
iDestX, iDestY,
|
|
0, 0, image->usWidth, image->usHeight);
|
|
#endif
|
|
break;
|
|
|
|
case 16:
|
|
SGP_THROW_IFFALSE(usIndex < hSrcVObject->usNumberOf16BPPObjects, L"index larger that number images");
|
|
image = &hSrcVObject->p16BPPObject[usIndex];
|
|
if ( fBltFlags & VO_BLT_SRCTRANSPARENCY )
|
|
{
|
|
Blt16BPPTo16BPPTrans( pBuffer, uiDestPitchBYTES,
|
|
image->p16BPPData, image->usWidth * sizeof(UINT16),
|
|
iDestX, iDestY,
|
|
0, 0, image->usWidth, image->usHeight, 0x1F ); // 0x1f = 5 bits of blue
|
|
}
|
|
else
|
|
{
|
|
Blt16BPPTo16BPP( pBuffer, uiDestPitchBYTES,
|
|
image->p16BPPData, image->usWidth * sizeof(UINT16),
|
|
iDestX, iDestY,
|
|
0, 0, image->usWidth, image->usHeight );
|
|
}
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
SGP_THROW_IFFALSE( hSrcVObject->usNumberOfObjects > usIndex, L"Video object index is larger than the number of subimages");
|
|
// Switch based on flags given
|
|
do
|
|
{
|
|
if(gbPixelDepth==16)
|
|
{
|
|
#ifndef JA2
|
|
if ( fBltFlags & VO_BLT_MIRROR_Y)
|
|
{
|
|
if(!BltIsClipped(hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect))
|
|
Blt8BPPDataTo16BPPBufferTransMirror( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex );
|
|
// CLipping version not done -- DB
|
|
// Blt8BPPDataTo16BPPBufferTransMirrorClip( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect);
|
|
break;
|
|
}
|
|
else
|
|
#endif
|
|
if ( fBltFlags & VO_BLT_SRCTRANSPARENCY )
|
|
{
|
|
if(BltIsClipped(hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect))
|
|
Blt8BPPDataTo16BPPBufferTransparentClip( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect);
|
|
else
|
|
Blt8BPPDataTo16BPPBufferTransparent( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex );
|
|
break;
|
|
}
|
|
else if ( fBltFlags & VO_BLT_SHADOW )
|
|
{
|
|
if(BltIsClipped(hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect))
|
|
Blt8BPPDataTo16BPPBufferShadowClip( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect);
|
|
else
|
|
Blt8BPPDataTo16BPPBufferShadow( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex );
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if(gbPixelDepth==8)
|
|
{
|
|
if ( fBltFlags & VO_BLT_SRCTRANSPARENCY )
|
|
{
|
|
if(BltIsClipped(hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect))
|
|
Blt8BPPDataTo8BPPBufferTransparentClip( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect);
|
|
else
|
|
Blt8BPPDataTo8BPPBufferTransparent( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex );
|
|
break;
|
|
}
|
|
else if ( fBltFlags & VO_BLT_SHADOW )
|
|
{
|
|
if(BltIsClipped(hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect))
|
|
Blt8BPPDataTo8BPPBufferShadowClip( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect);
|
|
else
|
|
Blt8BPPDataTo8BPPBufferShadow( pBuffer, uiDestPitchBYTES, hSrcVObject, iDestX, iDestY, usIndex );
|
|
break;
|
|
}
|
|
}
|
|
// Use default blitter here
|
|
//Blt8BPPDataTo16BPPBuffer( hDestVObject, hSrcVObject, (UINT16)iDestX, (UINT16)iDestY, (SGPRect*)&SrcRect );
|
|
|
|
} while( FALSE );
|
|
|
|
break;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
//BF
|
|
//__except(filter(GetExceptionCode(), GetExceptionInformation()))
|
|
//{
|
|
// return ( TRUE );
|
|
//}
|
|
}
|
|
|
|
BOOLEAN PixelateVideoObjectRect( UINT32 uiDestVSurface, INT32 X1, INT32 Y1, INT32 X2, INT32 Y2)
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
SGPRect area;
|
|
UINT8 uiPattern[8][8]={ {0,1,0,1,0,1,0,1},
|
|
{1,0,1,0,1,0,1,0},
|
|
{0,1,0,1,0,1,0,1},
|
|
{1,0,1,0,1,0,1,0},
|
|
{0,1,0,1,0,1,0,1},
|
|
{1,0,1,0,1,0,1,0},
|
|
{0,1,0,1,0,1,0,1},
|
|
{1,0,1,0,1,0,1,0}};
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
area.iTop=Y1;
|
|
area.iBottom=Y2;
|
|
area.iLeft=X1;
|
|
area.iRight=X2;
|
|
|
|
// Now we have the video object and surface, call the shadow function
|
|
if(!Blt16BPPBufferPixelateRect(pBuffer, uiPitch, &area, uiPattern))
|
|
{
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
// Blit has failed if false returned
|
|
return( FALSE );
|
|
}
|
|
|
|
// Mark as dirty if it's the backbuffer
|
|
//if ( uiDestVSurface == BACKBUFFER )
|
|
//{
|
|
// InvalidateBackbuffer( );
|
|
//}
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
/**********************************************************************************************
|
|
DestroyObjectPaletteTables
|
|
|
|
Destroys the palette tables of a video object. All memory is deallocated, and
|
|
the pointers set to NULL. Be careful not to try and blit this object until new
|
|
tables are calculated, or things WILL go boom.
|
|
|
|
**********************************************************************************************/
|
|
BOOLEAN DestroyObjectPaletteTables(HVOBJECT hVObject)
|
|
{
|
|
UINT32 x;
|
|
BOOLEAN f16BitPal;
|
|
|
|
for ( x = 0; x < HVOBJECT_SHADE_TABLES; x++ )
|
|
{
|
|
if ( !( hVObject->fFlags & VOBJECT_FLAG_SHADETABLE_SHARED ) )
|
|
{
|
|
if ( hVObject->pShades[x] != NULL )
|
|
{
|
|
if ( hVObject->pShades[x] == hVObject->p16BPPPalette )
|
|
f16BitPal = TRUE;
|
|
else
|
|
f16BitPal = FALSE;
|
|
|
|
MemFree( hVObject->pShades[x] );
|
|
hVObject->pShades[x] = NULL;
|
|
|
|
if ( f16BitPal )
|
|
hVObject->p16BPPPalette = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( hVObject->p16BPPPalette != NULL )
|
|
{
|
|
MemFree( hVObject->p16BPPPalette );
|
|
hVObject->p16BPPPalette = NULL;
|
|
}
|
|
|
|
hVObject->pShadeCurrent=NULL;
|
|
hVObject->pGlow=NULL;
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT16 SetObjectShade(HVOBJECT pObj, UINT32 uiShade)
|
|
{
|
|
Assert(pObj!=NULL);
|
|
Assert(uiShade >= 0);
|
|
Assert(uiShade < HVOBJECT_SHADE_TABLES);
|
|
|
|
if(pObj->pShades[uiShade]==NULL)
|
|
{
|
|
DbgMessage(TOPIC_VIDEOOBJECT, DBG_LEVEL_2, String("Attempt to set shade level to NULL table"));
|
|
return(FALSE);
|
|
}
|
|
|
|
pObj->pShadeCurrent=pObj->pShades[uiShade];
|
|
return(TRUE);
|
|
}
|
|
|
|
UINT16 SetObjectHandleShade(UINT32 uiHandle, UINT32 uiShade)
|
|
{
|
|
HVOBJECT hObj;
|
|
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_SETOBJECTHANDLESHADE;
|
|
#endif
|
|
if(!GetVideoObject(&hObj, uiHandle))
|
|
{
|
|
DbgMessage(TOPIC_VIDEOOBJECT, DBG_LEVEL_2, String("Invalid object handle for setting shade level"));
|
|
return(FALSE);
|
|
}
|
|
return(SetObjectShade(hObj, uiShade));
|
|
}
|
|
|
|
/*
|
|
UINT16 FillObjectRect(UINT32 iObj, INT32 x1, INT32 y1, INT32 x2, INT32 y2, COLORVAL color32)
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
//HVSURFACE pSurface;
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface(iObj, &uiPitch );
|
|
//UnLockVideoSurface(iObj);
|
|
|
|
|
|
if (pBuffer == NULL)
|
|
return( FALSE );
|
|
|
|
FillRect16BPP(pBuffer, uiPitch, x1, y1, x2, y2, Get16BPPColor(color32));
|
|
|
|
// Mark as dirty if it's the backbuffer
|
|
if(iObj == BACKBUFFER)
|
|
InvalidateBackbuffer();
|
|
|
|
UnLockVideoSurface(iObj);
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
/********************************************************************************************
|
|
GetETRLEPixelValue
|
|
|
|
Given a VOBJECT and ETRLE image index, retrieves the value of the pixel located at the
|
|
given image coordinates. The value returned is an 8-bit palette index
|
|
********************************************************************************************/
|
|
BOOLEAN GetETRLEPixelValue( UINT8 * pDest, HVOBJECT hVObject, UINT16 usETRLEIndex, UINT16 usX, UINT16 usY )
|
|
{
|
|
UINT8 * pCurrent;
|
|
UINT16 usLoopX = 0;
|
|
UINT16 usLoopY = 0;
|
|
UINT16 ubRunLength;
|
|
ETRLEObject * pETRLEObject;
|
|
|
|
// Do a bunch of checks
|
|
CHECKF( hVObject != NULL );
|
|
CHECKF( usETRLEIndex < hVObject->usNumberOfObjects );
|
|
|
|
pETRLEObject = &(hVObject->pETRLEObject[usETRLEIndex]);
|
|
|
|
CHECKF( usX < pETRLEObject->usWidth );
|
|
CHECKF( usY < pETRLEObject->usHeight );
|
|
|
|
// Assuming everything's okay, go ahead and look...
|
|
pCurrent = &((UINT8 *)hVObject->pPixData)[pETRLEObject->uiDataOffset];
|
|
|
|
// Skip past all uninteresting scanlines
|
|
while( usLoopY < usY )
|
|
{
|
|
while( *pCurrent != 0 )
|
|
{
|
|
if (*pCurrent & COMPRESS_TRANSPARENT)
|
|
{
|
|
pCurrent++;
|
|
}
|
|
else
|
|
{
|
|
pCurrent += *pCurrent & COMPRESS_RUN_MASK;
|
|
}
|
|
}
|
|
usLoopY++;
|
|
}
|
|
|
|
// Now look in this scanline for the appropriate byte
|
|
do
|
|
{
|
|
ubRunLength = *pCurrent & COMPRESS_RUN_MASK;
|
|
|
|
if (*pCurrent & COMPRESS_TRANSPARENT)
|
|
{
|
|
if (usLoopX + ubRunLength >= usX)
|
|
{
|
|
*pDest = 0;
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
pCurrent++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (usLoopX + ubRunLength >= usX)
|
|
{
|
|
// skip to the correct byte; skip at least 1 to get past the byte defining the run
|
|
pCurrent += (usX - usLoopX) + 1;
|
|
*pDest = *pCurrent;
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
pCurrent += ubRunLength + 1;
|
|
}
|
|
}
|
|
usLoopX += ubRunLength;
|
|
}
|
|
while( usLoopX < usX );
|
|
// huh???
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN GetVideoObjectETRLEProperties( HVOBJECT hVObject, ETRLEObject *pETRLEObject, UINT16 usIndex )
|
|
{
|
|
CHECKF( usIndex >= 0 );
|
|
CHECKF( usIndex < hVObject->usNumberOfObjects );
|
|
|
|
memcpy( pETRLEObject, &( hVObject->pETRLEObject[ usIndex ] ), sizeof( ETRLEObject ) );
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
BOOLEAN GetVideoObjectETRLESubregionProperties( UINT32 uiVideoObject, UINT16 usIndex, UINT16 *pusWidth, UINT16 *pusHeight )
|
|
{
|
|
HVOBJECT hVObject;
|
|
ETRLEObject ETRLEObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_GETVIDEOOBJECTETRLESUBREGIONPROPERTIES;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiVideoObject ) );
|
|
|
|
CHECKF( GetVideoObjectETRLEProperties( hVObject, &ETRLEObject, usIndex ) );
|
|
|
|
*pusWidth = ETRLEObject.usWidth;
|
|
*pusHeight = ETRLEObject.usHeight;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN GetVideoObjectETRLEPropertiesFromIndex( UINT32 uiVideoObject, ETRLEObject *pETRLEObject, UINT16 usIndex )
|
|
{
|
|
HVOBJECT hVObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_GETVIDEOOBJECTETRLEPROPERTIESFROMINDEX;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiVideoObject ) );
|
|
|
|
CHECKF( GetVideoObjectETRLEProperties( hVObject, pETRLEObject, usIndex ) );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN SetVideoObjectPalette8BPP(INT32 uiVideoObject, SGPPaletteEntry *pPal8)
|
|
{
|
|
HVOBJECT hVObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_SETVIDEOOBJECTPALETTE8BPP;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiVideoObject ) );
|
|
|
|
return( SetVideoObjectPalette( hVObject, pPal8 ) );
|
|
}
|
|
|
|
|
|
BOOLEAN GetVideoObjectPalette16BPP(INT32 uiVideoObject, UINT16 **ppPal16)
|
|
{
|
|
HVOBJECT hVObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_GETVIDEOOBJECTPALETTE16BPP;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiVideoObject ) );
|
|
|
|
*ppPal16 = hVObject->p16BPPPalette;
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN CopyVideoObjectPalette16BPP(INT32 uiVideoObject, UINT16 *ppPal16)
|
|
{
|
|
HVOBJECT hVObject;
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_COPYVIDEOOBJECTPALETTE16BPP;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hVObject, uiVideoObject ) );
|
|
|
|
memcpy(ppPal16, hVObject->p16BPPPalette, 256*2);
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN CheckFor16BPPRegion( HVOBJECT hVObject, UINT16 usRegionIndex, UINT8 ubShadeLevel, UINT16 * pusIndex )
|
|
{
|
|
UINT16 usLoop;
|
|
SixteenBPPObjectInfo * p16BPPObject;
|
|
|
|
if (hVObject->usNumberOf16BPPObjects > 0)
|
|
{
|
|
for (usLoop = 0; usLoop < hVObject->usNumberOf16BPPObjects; usLoop++)
|
|
{
|
|
p16BPPObject = &(hVObject->p16BPPObject[usLoop]);
|
|
if (p16BPPObject->usRegionIndex == usRegionIndex && p16BPPObject->ubShadeLevel == ubShadeLevel)
|
|
{
|
|
if (pusIndex != NULL)
|
|
{
|
|
*pusIndex = usLoop;
|
|
}
|
|
return( TRUE );
|
|
}
|
|
}
|
|
}
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN ConvertVObjectRegionTo16BPP( HVOBJECT hVObject, UINT16 usRegionIndex, UINT8 ubShadeLevel )
|
|
{
|
|
SixteenBPPObjectInfo * p16BPPObject;
|
|
UINT8 * pInput;
|
|
UINT8 * pOutput;
|
|
UINT16 * p16BPPPalette;
|
|
UINT32 uiDataLoop;
|
|
UINT32 uiDataLength;
|
|
UINT8 ubRunLoop;
|
|
//UINT8 ubRunLength;
|
|
INT8 bData;
|
|
UINT32 uiLen;
|
|
|
|
// check for existing 16BPP region and then allocate memory
|
|
if (usRegionIndex >= hVObject->usNumberOfObjects || ubShadeLevel >= HVOBJECT_SHADE_TABLES)
|
|
{
|
|
return( FALSE );
|
|
}
|
|
if (CheckFor16BPPRegion( hVObject, usRegionIndex, ubShadeLevel, NULL) == TRUE)
|
|
{
|
|
// it already exists; no need to do anything!
|
|
return( TRUE );
|
|
}
|
|
|
|
if (hVObject->usNumberOf16BPPObjects > 0)
|
|
{
|
|
// have to reallocate memory
|
|
hVObject->p16BPPObject = (SixteenBPPObjectInfo *) MemRealloc( hVObject->p16BPPObject, sizeof( SixteenBPPObjectInfo ) * (hVObject->usNumberOf16BPPObjects + 1) );
|
|
}
|
|
else
|
|
{
|
|
// allocate memory for the first 16BPPObject
|
|
hVObject->p16BPPObject = (SixteenBPPObjectInfo *) MemAlloc( sizeof( SixteenBPPObjectInfo ) );
|
|
}
|
|
if (hVObject->p16BPPObject == NULL)
|
|
{
|
|
hVObject->usNumberOf16BPPObjects = 0;
|
|
return( FALSE );
|
|
}
|
|
|
|
// the new object is the last one in the array
|
|
p16BPPObject = &(hVObject->p16BPPObject[hVObject->usNumberOf16BPPObjects]);
|
|
|
|
// need twice as much memory because of going from 8 to 16 bits
|
|
p16BPPObject->p16BPPData = (UINT16 *) MemAlloc( hVObject->pETRLEObject[usRegionIndex].uiDataLength * 2 );
|
|
if (p16BPPObject->p16BPPData == NULL)
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
p16BPPObject->usRegionIndex = usRegionIndex;
|
|
p16BPPObject->ubShadeLevel = ubShadeLevel;
|
|
p16BPPObject->usHeight = hVObject->pETRLEObject[ usRegionIndex ].usHeight;
|
|
p16BPPObject->usWidth = hVObject->pETRLEObject[ usRegionIndex ].usWidth;
|
|
p16BPPObject->sOffsetX=hVObject->pETRLEObject[ usRegionIndex ].sOffsetX;
|
|
p16BPPObject->sOffsetY=hVObject->pETRLEObject[ usRegionIndex ].sOffsetY;
|
|
|
|
// get the palette
|
|
p16BPPPalette = hVObject->pShades[ubShadeLevel];
|
|
pInput = (UINT8 *) hVObject->pPixData + hVObject->pETRLEObject[ usRegionIndex ].uiDataOffset;
|
|
|
|
uiDataLength=hVObject->pETRLEObject[usRegionIndex].uiDataLength;
|
|
|
|
// now actually do the conversion
|
|
|
|
uiLen=0;
|
|
pOutput = (UINT8 *)p16BPPObject->p16BPPData;
|
|
for (uiDataLoop = 0; uiDataLoop < uiDataLength; uiDataLoop++)
|
|
{
|
|
bData= *pInput;
|
|
if(bData&0x80)
|
|
{
|
|
// transparent
|
|
*pOutput = *pInput;
|
|
pOutput++;
|
|
pInput++;
|
|
//uiDataLoop++;
|
|
uiLen+=(UINT32)(bData&0x7f);
|
|
}
|
|
else if(bData > 0)
|
|
{
|
|
// nontransparent
|
|
*pOutput = *pInput;
|
|
pOutput++;
|
|
pInput++;
|
|
//uiDataLoop++;
|
|
for(ubRunLoop=0; ubRunLoop < bData; ubRunLoop++)
|
|
{
|
|
*((UINT16 *)pOutput) = p16BPPPalette[*pInput];
|
|
pOutput++;
|
|
pOutput++;
|
|
pInput++;
|
|
uiDataLoop++;
|
|
}
|
|
uiLen+=(UINT32)bData;
|
|
}
|
|
else
|
|
{
|
|
// eol
|
|
*pOutput = *pInput;
|
|
pOutput++;
|
|
pInput++;
|
|
//uiDataLoop++;
|
|
if(uiLen!=p16BPPObject->usWidth)
|
|
DbgMessage(TOPIC_VIDEOOBJECT, DBG_LEVEL_1, String( "Actual pixel width different from header width" ));
|
|
uiLen=0;
|
|
}
|
|
|
|
// copy the run-length byte
|
|
/* *pOutput = *pInput;
|
|
pOutput++;
|
|
if (((*pInput) & COMPRESS_TRANSPARENT) == 0 && *pInput > 0)
|
|
{
|
|
// non-transparent run; deal with the pixel data
|
|
ubRunLoop = 0;
|
|
ubRunLength = ((*pInput) & COMPRESS_RUN_LIMIT);
|
|
// skip to the next input byte
|
|
pInput++;
|
|
for (ubRunLoop = 0; ubRunLoop < ubRunLength; ubRunLoop++)
|
|
{
|
|
*((UINT16 *)pOutput) = p16BPPPalette[*pInput];
|
|
// advance two bytes in output, one in input
|
|
pOutput++;
|
|
pOutput++;
|
|
pInput++;
|
|
uiDataLoop++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// transparent run or end of scanline; skip to the next input byte
|
|
pInput++;
|
|
} */
|
|
}
|
|
hVObject->usNumberOf16BPPObjects++;
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN BltVideoObjectOutlineFromIndex(UINT32 uiDestVSurface, UINT32 uiSrcVObject, UINT16 usIndex, INT32 iDestX, INT32 iDestY, INT16 s16BPPColor, BOOLEAN fDoOutline )
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
HVOBJECT hSrcVObject;
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_BLTVIDEOOBJECTOUTLINEFROMINDEX;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hSrcVObject, uiSrcVObject ) );
|
|
|
|
if( BltIsClipped( hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect) )
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, s16BPPColor, fDoOutline, &ClippingRect );
|
|
}
|
|
else
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutline((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, s16BPPColor, fDoOutline );
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN BltVideoObjectOutline(UINT32 uiDestVSurface, HVOBJECT hSrcVObject, UINT16 usIndex, INT32 iDestX, INT32 iDestY, INT16 s16BPPColor, BOOLEAN fDoOutline )
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if( BltIsClipped( hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect) )
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineClip((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, s16BPPColor, fDoOutline, &ClippingRect );
|
|
}
|
|
else
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutline((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, s16BPPColor, fDoOutline );
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN BltVideoObjectOutlineShadowFromIndex(UINT32 uiDestVSurface, UINT32 uiSrcVObject, UINT16 usIndex, INT32 iDestX, INT32 iDestY )
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
HVOBJECT hSrcVObject;
|
|
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// Get video object
|
|
#ifdef _DEBUG
|
|
gubVODebugCode = DEBUGSTR_BLTVIDEOOBJECTOUTLINESHADOWFROMINDEX;
|
|
#endif
|
|
CHECKF( GetVideoObject( &hSrcVObject, uiSrcVObject ) );
|
|
|
|
if(hSrcVObject->ubBitDepth == 8)
|
|
{
|
|
if( BltIsClipped( hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect) )
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineShadowClip((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect );
|
|
}
|
|
else
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineShadow((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex );
|
|
}
|
|
}
|
|
else if(hSrcVObject->ubBitDepth == 16)
|
|
{
|
|
SGP_THROW_IFFALSE(usIndex < hSrcVObject->usNumberOf16BPPObjects, L"index larger that number images");
|
|
SixteenBPPObjectInfo &image = hSrcVObject->p16BPPObject[0];
|
|
Blt16BPPTo16BPPTransShadow(pBuffer, uiPitch, image.p16BPPData, image.usWidth * sizeof(UINT16),
|
|
iDestX, iDestY, 0, 0, image.usWidth, image.usHeight, 0x1F);
|
|
}
|
|
else if(hSrcVObject->ubBitDepth == 32)
|
|
{
|
|
SGP_THROW_IFFALSE(usIndex < hSrcVObject->usNumberOf16BPPObjects, L"index larger that number images");
|
|
SixteenBPPObjectInfo &image = hSrcVObject->p16BPPObject[0];
|
|
Blt32BPPTo16BPPTransShadow(pBuffer, uiPitch, (UINT32*)image.p16BPPData, image.usWidth * sizeof(UINT32),
|
|
iDestX, iDestY, 0, 0, image.usWidth, image.usHeight);
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOLEAN BltVideoObjectOutlineShadow(UINT32 uiDestVSurface, HVOBJECT hSrcVObject, UINT16 usIndex, INT32 iDestX, INT32 iDestY )
|
|
{
|
|
UINT16 *pBuffer;
|
|
UINT32 uiPitch;
|
|
// Lock video surface
|
|
pBuffer = (UINT16*)LockVideoSurface( uiDestVSurface, &uiPitch );
|
|
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
if( BltIsClipped( hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect) )
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineShadowClip((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex, &ClippingRect );
|
|
}
|
|
else
|
|
{
|
|
Blt8BPPDataTo16BPPBufferOutlineShadow((UINT16*)pBuffer, uiPitch, hSrcVObject, iDestX, iDestY, usIndex );
|
|
}
|
|
|
|
// Now we have the video object and surface, call the VO blitter function
|
|
|
|
UnLockVideoSurface( uiDestVSurface );
|
|
return( TRUE );
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void CheckValidVObjectIndex( UINT32 uiIndex )
|
|
{
|
|
BOOLEAN fAssertError = FALSE;
|
|
if( uiIndex == 0xffffffff )
|
|
{ //-1 index -- deleted
|
|
fAssertError = TRUE;
|
|
}
|
|
if( !(uiIndex % 2) && uiIndex < 0xfffffff0 || uiIndex >= 0xfffffff0 )
|
|
{ //even numbers are reserved for vsurfaces as well as the 0xfffffff0+ values
|
|
fAssertError = TRUE;
|
|
}
|
|
|
|
if( fAssertError )
|
|
{
|
|
CHAR8 str[60];
|
|
switch( gubVODebugCode )
|
|
{
|
|
case DEBUGSTR_SETVIDEOOBJECTTRANSPARENCY:
|
|
sprintf( str, "SetVideoObjectTransparency" );
|
|
break;
|
|
case DEBUGSTR_BLTVIDEOOBJECTFROMINDEX:
|
|
sprintf( str, "BltVideoObjectFromIndex" );
|
|
break;
|
|
case DEBUGSTR_SETOBJECTHANDLESHADE:
|
|
sprintf( str, "SetObjectHandleShade" );
|
|
break;
|
|
case DEBUGSTR_GETVIDEOOBJECTETRLESUBREGIONPROPERTIES:
|
|
sprintf( str, "GetVideoObjectETRLESubRegionProperties" );
|
|
break;
|
|
case DEBUGSTR_GETVIDEOOBJECTETRLEPROPERTIESFROMINDEX:
|
|
sprintf( str, "GetVideoObjectETRLEPropertiesFromIndex" );
|
|
break;
|
|
case DEBUGSTR_SETVIDEOOBJECTPALETTE8BPP:
|
|
sprintf( str, "SetVideoObjectPalette8BPP" );
|
|
break;
|
|
case DEBUGSTR_GETVIDEOOBJECTPALETTE16BPP:
|
|
sprintf( str, "GetVideoObjectPalette16BPP" );
|
|
break;
|
|
case DEBUGSTR_COPYVIDEOOBJECTPALETTE16BPP:
|
|
sprintf( str, "CopyVideoObjectPalette16BPP" );
|
|
break;
|
|
case DEBUGSTR_BLTVIDEOOBJECTOUTLINEFROMINDEX:
|
|
sprintf( str, "BltVideoObjectOutlineFromIndex" );
|
|
break;
|
|
case DEBUGSTR_BLTVIDEOOBJECTOUTLINESHADOWFROMINDEX:
|
|
sprintf( str, "BltVideoObjectOutlineShadowFromIndex" );
|
|
break;
|
|
case DEBUGSTR_DELETEVIDEOOBJECTFROMINDEX:
|
|
sprintf( str, "DeleteVideoObjectFromIndex" );
|
|
break;
|
|
case DEBUGSTR_NONE:
|
|
default:
|
|
sprintf( str, "GetVideoObject" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef SGP_VIDEO_DEBUGGING
|
|
|
|
typedef struct DUMPFILENAME
|
|
{
|
|
CHAR8 str[256];
|
|
}DUMPFILENAME;
|
|
|
|
void DumpVObjectInfoIntoFile( const STR8 filename, BOOLEAN fAppend )
|
|
{
|
|
VOBJECT_NODE *curr;
|
|
FILE *fp;
|
|
DUMPFILENAME *pName, *pCode;
|
|
UINT32 *puiCounter;
|
|
CHAR8 tempName[ 256 ];
|
|
CHAR8 tempCode[ 256 ];
|
|
UINT32 i, uiUniqueID;
|
|
BOOLEAN fFound;
|
|
if( !guiVObjectSize )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( fAppend )
|
|
{
|
|
fp = fopen( filename, "a" );
|
|
}
|
|
else
|
|
{
|
|
fp = fopen( filename, "w" );
|
|
}
|
|
Assert( fp );
|
|
|
|
//Allocate enough strings and counters for each node.
|
|
pName = (DUMPFILENAME*)MemAlloc( sizeof( DUMPFILENAME ) * guiVObjectSize );
|
|
pCode = (DUMPFILENAME*)MemAlloc( sizeof( DUMPFILENAME ) * guiVObjectSize );
|
|
memset( pName, 0, sizeof( DUMPFILENAME ) * guiVObjectSize );
|
|
memset( pCode, 0, sizeof( DUMPFILENAME ) * guiVObjectSize );
|
|
puiCounter = (UINT32*)MemAlloc( 4 * guiVObjectSize );
|
|
memset( puiCounter, 0, 4 * guiVObjectSize );
|
|
|
|
//Loop through the list and record every unique filename and count them
|
|
uiUniqueID = 0;
|
|
curr = gpVObjectHead;
|
|
while( curr )
|
|
{
|
|
strcpy( tempName, curr->pName );
|
|
strcpy( tempCode, curr->pCode );
|
|
fFound = FALSE;
|
|
for( i = 0; i < uiUniqueID; i++ )
|
|
{
|
|
if( !_stricmp( tempName, pName[i].str ) && !_stricmp( tempCode, pCode[i].str ) )
|
|
{ //same string
|
|
fFound = TRUE;
|
|
(puiCounter[ i ])++;
|
|
break;
|
|
}
|
|
}
|
|
if( !fFound )
|
|
{
|
|
strcpy( pName[i].str, tempName );
|
|
strcpy( pCode[i].str, tempCode );
|
|
(puiCounter[ i ])++;
|
|
uiUniqueID++;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
|
|
//Now dump the info.
|
|
fprintf( fp, "-----------------------------------------------\n" );
|
|
fprintf( fp, "%d unique vObject names exist in %d VObjects\n", uiUniqueID, guiVObjectSize );
|
|
fprintf( fp, "-----------------------------------------------\n\n" );
|
|
for( i = 0; i < uiUniqueID; i++ )
|
|
{
|
|
fprintf( fp, "%d occurrences of %s\n", puiCounter[i], pName[i].str );
|
|
fprintf( fp, "%s\n\n", pCode[i].str );
|
|
}
|
|
fprintf( fp, "\n-----------------------------------------------\n\n" );
|
|
|
|
//Free all memory associated with this operation.
|
|
MemFree( pName );
|
|
MemFree( pCode );
|
|
MemFree( puiCounter );
|
|
fclose( fp );
|
|
}
|
|
|
|
//Debug wrapper for adding vObjects
|
|
BOOLEAN _AddAndRecordVObject( VOBJECT_DESC *VObjectDesc, UINT32 *uiIndex, UINT32 uiLineNum, const STR8 pSourceFile )
|
|
{
|
|
UINT16 usLength;
|
|
CHAR8 str[256];
|
|
if( !AddStandardVideoObject( VObjectDesc, uiIndex ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//record the filename of the vObject (some are created via memory though)
|
|
usLength = strlen( VObjectDesc->ImageFile ) + 1;
|
|
gpVObjectTail->pName = (STR8)MemAlloc( usLength );
|
|
memset( gpVObjectTail->pName, 0, usLength );
|
|
strcpy( gpVObjectTail->pName, VObjectDesc->ImageFile );
|
|
|
|
//record the code location of the calling creating function.
|
|
sprintf( str, "%s -- line(%d)", pSourceFile, uiLineNum );
|
|
usLength = strlen( str ) + 1;
|
|
gpVObjectTail->pCode = (STR8)MemAlloc( usLength );
|
|
memset( gpVObjectTail->pCode, 0, usLength );
|
|
strcpy( gpVObjectTail->pCode, str );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void PerformVideoInfoDumpIntoFile( const STR8 filename, BOOLEAN fAppend )
|
|
{
|
|
DumpVObjectInfoIntoFile( filename, fAppend );
|
|
DumpVSurfaceInfoIntoFile( filename, TRUE );
|
|
}
|
|
|
|
#endif
|
|
|
|
|