Files
source/sgp/Cursor Control.cpp
T
majcostaandGitHub 381ab936eb Rename 'Standard Gaming Platform' to 'sgp' (#246)
* rename 'Standard Gaming Platform' to 'sgp'

* Adapt CMakeLists.txt files to renamed SGP directory

* Lowercase it
2023-10-23 10:18:20 -03:00

628 lines
16 KiB
C++

#include "Cursor Control.h"
#include "video.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Cursor Database
//
///////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN gfCursorDatabaseInit = FALSE;
CursorFileData *gpCursorFileDatabase;
CursorData *gpCursorDatabase;
INT16 gsGlobalCursorYOffset = 0;
INT16 gsCurMouseOffsetX = 0;
INT16 gsCurMouseOffsetY = 0;
UINT16 gsCurMouseHeight = 0;
UINT16 gsCurMouseWidth = 0;
UINT16 gusNumDataFiles = 0;
UINT32 guiExternVo;
UINT16 gusExternVoSubIndex;
UINT32 guiExtern2Vo;
UINT16 gusExtern2VoSubIndex;
UINT32 guiOldSetCursor = 0;
UINT32 guiDelayTimer = 0;
MOUSEBLT_HOOK gMouseBltOverride = NULL;
BOOLEAN BltToMouseCursorFromVObject( HVOBJECT hVObject, UINT16 usVideoObjectSubIndex, UINT16 usXPos, UINT16 usYPos )
{
BOOLEAN ReturnValue;
ReturnValue = BltVideoObject(MOUSE_BUFFER, hVObject, usVideoObjectSubIndex, usXPos, usYPos, VO_BLT_SRCTRANSPARENCY, NULL);
return ReturnValue;
}
BOOLEAN BltToMouseCursorFromVObjectWithOutline( HVOBJECT hVObject, UINT16 usVideoObjectSubIndex, UINT16 usXPos, UINT16 usYPos )
{
BOOLEAN ReturnValue;
ETRLEObject *pTrav;
INT16 sXPos, sYPos;
// Adjust for offsets
pTrav = &(hVObject->pETRLEObject[ usVideoObjectSubIndex ] );
sXPos = 0;
sYPos = 0;
// Remove offsets...
sXPos -= pTrav->sOffsetX;
sYPos -= pTrav->sOffsetY;
// Center!
sXPos += ( ( gsCurMouseWidth - pTrav->usWidth ) / 2 );
sYPos += ( ( gsCurMouseHeight - pTrav->usHeight ) / 2 );
ReturnValue = BltVideoObjectOutline(MOUSE_BUFFER, hVObject, usVideoObjectSubIndex, sXPos, sYPos, Get16BPPColor( FROMRGB( 0, 255, 0 ) ), TRUE );
return ReturnValue;
}
// THESE TWO PARAMETERS MUST POINT TO STATIC OR GLOBAL DATA, NOT AUTOMATIC VARIABLES
void InitCursorDatabase( CursorFileData *pCursorFileData, CursorData *pCursorData, UINT16 suNumDataFiles )
{
// Set global values!
gpCursorFileDatabase = pCursorFileData;
gpCursorDatabase = pCursorData;
gusNumDataFiles = suNumDataFiles;
gfCursorDatabaseInit = TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Cursor Handlers
//
///////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN LoadCursorData(UINT32 uiCursorIndex)
{
// Load cursor data will load all data required for the cursor specified by this index
CursorData *pCurData;
CursorImage *pCurImage;
UINT32 cnt;
INT16 sMaxHeight = -1;
INT16 sMaxWidth = -1;
ETRLEObject *pTrav;
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
pCurImage = &( pCurData->Composites[ cnt ] );
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].fLoaded == FALSE )
{
//
// The file containing the video object hasn't been loaded yet. Let's load it now
//
VOBJECT_DESC VideoObjectDescription;
// FIRST LOAD AS AN HIMAGE SO WE CAN GET AUX DATA!
HIMAGE hImage;
AuxObjectData *pAuxData;
// ATE: First check if we are using an extern vo cursor...
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFlags & USE_EXTERN_VO_CURSOR )
{
// Let's check if we have NOT NULL here...
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject == NULL )
{
// Something wrong here...
}
}
else
{
hImage = CreateImage( (CHAR8 *)gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFilename, IMAGE_ALLDATA );
if (hImage == NULL)
{
return( FALSE );
}
VideoObjectDescription.fCreateFlags = VOBJECT_CREATE_FROMHIMAGE;
VideoObjectDescription.hImage = hImage;
if ( !AddVideoObject( &VideoObjectDescription, &( gpCursorFileDatabase[ pCurImage->uiFileIndex ].uiIndex) ) )
{
return( FALSE );
}
// Check for animated tile
if (hImage->uiAppDataSize > 0 )
{
// Valid auxiliary data, so get # od frames from data
pAuxData = ( AuxObjectData* ) hImage->pAppData;
if ( pAuxData->fFlags & AUX_ANIMATED_TILE )
{
gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFlags |= ANIMATED_CURSOR;
gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubNumberOfFrames = pAuxData->ubNumberOfFrames;
}
}
// the hImage is no longer needed
DestroyImage( hImage );
// Save hVObject....
GetVideoObject( &(gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject), gpCursorFileDatabase[ pCurImage->uiFileIndex ].uiIndex );
}
gpCursorFileDatabase[ pCurImage->uiFileIndex ].fLoaded = TRUE;
}
// Get ETRLE Data for this video object
pTrav = &(gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject->pETRLEObject[ pCurImage->uiSubIndex ] );
if( !pTrav )
{
return FALSE;
}
if ( pTrav->usHeight > sMaxHeight )
{
sMaxHeight = pTrav->usHeight;
}
if ( pTrav->usWidth > sMaxWidth )
{
sMaxWidth = pTrav->usWidth;
}
}
pCurData->usHeight = sMaxHeight;
pCurData->usWidth = sMaxWidth;
if ( pCurData->sOffsetX == CENTER_CURSOR )
{
pCurData->sOffsetX = ( pCurData->usWidth / 2 );
}
if ( pCurData->sOffsetX == RIGHT_CURSOR )
{
pCurData->sOffsetX = pCurData->usWidth;
}
if ( pCurData->sOffsetX == LEFT_CURSOR )
{
pCurData->sOffsetX = 0;
}
if ( pCurData->sOffsetY == CENTER_CURSOR )
{
pCurData->sOffsetY = ( pCurData->usHeight / 2 );
}
if ( pCurData->sOffsetY == BOTTOM_CURSOR )
{
pCurData->sOffsetY = pCurData->usHeight;
}
if ( pCurData->sOffsetY == TOP_CURSOR )
{
pCurData->sOffsetY = 0;
}
gsCurMouseOffsetX = pCurData->sOffsetX;
gsCurMouseOffsetY = pCurData->sOffsetY;
gsCurMouseHeight = pCurData->usHeight;
gsCurMouseWidth = pCurData->usWidth;
// Adjust relative offsets
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
pCurImage = &( pCurData->Composites[ cnt ] );
// Get ETRLE Data for this video object
pTrav = &(gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject->pETRLEObject[ pCurImage->uiSubIndex ] );
if( !pTrav )
{
return FALSE;
}
if ( pCurImage->usPosX == CENTER_SUBCURSOR )
{
pCurImage->usPosX = pCurData->sOffsetX - ( pTrav->usWidth / 2 );
}
if ( pCurImage->usPosY == CENTER_SUBCURSOR )
{
pCurImage->usPosY = pCurData->sOffsetY - ( pTrav->usHeight / 2 );
}
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void UnLoadCursorData(UINT32 uiCursorIndex)
{
// This function will unload add data used for this cursor
//
// Ok, first we make sure that the video object file is indeed loaded. Once this is verified, we will
// move on to the deletion
//
CursorData *pCurData;
CursorImage *pCurImage;
UINT32 cnt;
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
pCurImage = &( pCurData->Composites[ cnt ] );
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].fLoaded )
{
if ( !( gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFlags & USE_EXTERN_VO_CURSOR ) )
{
DeleteVideoObjectFromIndex( gpCursorFileDatabase[ pCurImage->uiFileIndex ].uiIndex);
gpCursorFileDatabase[ pCurImage->uiFileIndex ].uiIndex = 0;
}
gpCursorFileDatabase[ pCurImage->uiFileIndex ].fLoaded = FALSE;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void CursorDatabaseClear(void)
{
UINT32 uiIndex;
for (uiIndex = 0; uiIndex < gusNumDataFiles; uiIndex++)
{
if (gpCursorFileDatabase[uiIndex].fLoaded == TRUE)
{
if ( !( gpCursorFileDatabase[ uiIndex ].ubFlags & USE_EXTERN_VO_CURSOR ) )
{
DeleteVideoObjectFromIndex( gpCursorFileDatabase[uiIndex].uiIndex);
gpCursorFileDatabase[uiIndex].uiIndex = 0;
}
gpCursorFileDatabase[uiIndex].fLoaded = FALSE;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN SetCurrentCursorFromDatabase( UINT32 uiCursorIndex )
{
BOOLEAN ReturnValue = TRUE;
UINT16 usSubIndex;
CursorData *pCurData;
CursorImage *pCurImage;
UINT32 cnt;
INT16 sCenterValX, sCenterValY;
HVOBJECT hVObject;
ETRLEObject *pTrav;
UINT16 usEffHeight, usEffWidth;
if ( gfCursorDatabaseInit )
{
// If the current cursor is the first index, disable cursors
if ( uiCursorIndex == VIDEO_NO_CURSOR )
{
EraseMouseCursor( );
SetMouseCursorProperties( 0, 0, 5, 5 );
DirtyCursor( );
//EnableCursor( FALSE );
}
else
{
// CHECK FOR EXTERN CURSOR
if ( uiCursorIndex == EXTERN_CURSOR || uiCursorIndex == EXTERN2_CURSOR )
{
INT16 sSubX, sSubY;
HVOBJECT hVObjectTemp;
ETRLEObject *pTravTemp;
// Erase old cursor
EraseMouseCursor( );
if ( uiCursorIndex == EXTERN2_CURSOR )
{
// Get ETRLE values
GetVideoObject( &hVObject, guiExtern2Vo );
pTrav = &(hVObject->pETRLEObject[ gusExtern2VoSubIndex ] );
}
else
{
// Get ETRLE values
GetVideoObject( &hVObject, guiExternVo );
pTrav = &(hVObject->pETRLEObject[ gusExternVoSubIndex ] );
}
// Determine center
sCenterValX = 0;
sCenterValY = 0;
// Effective height
usEffHeight = pTrav->usHeight + pTrav->sOffsetY;
usEffWidth = pTrav->usWidth + pTrav->sOffsetX;
// ATE: Check for extern 2nd...
if ( uiCursorIndex == EXTERN2_CURSOR )
{
BltVideoObjectOutlineFromIndex( MOUSE_BUFFER, guiExtern2Vo, gusExtern2VoSubIndex, 0, 0, 0, FALSE );
// Get ETRLE values
GetVideoObject( &hVObjectTemp, guiExternVo );
pTravTemp = &(hVObjectTemp->pETRLEObject[ gusExternVoSubIndex ] );
sSubX = ( pTrav->usWidth - pTravTemp->usWidth - pTravTemp->sOffsetX ) / 2;
sSubY = ( pTrav->usHeight - pTravTemp->usHeight - pTravTemp->sOffsetY ) / 2;
BltVideoObjectOutlineFromIndex( MOUSE_BUFFER, guiExternVo, gusExternVoSubIndex, sSubX, sSubY, 0, FALSE );
}
else
{
BltVideoObjectOutlineFromIndex( MOUSE_BUFFER, guiExternVo, gusExternVoSubIndex, 0, 0, 0, FALSE );
}
// Hook into hook function
if ( gMouseBltOverride != NULL )
{
gMouseBltOverride( );
}
SetMouseCursorProperties( (INT16)(usEffWidth/2), (INT16)(usEffHeight/2), (UINT16)(usEffHeight), (UINT16)(usEffWidth ) );
DirtyCursor( );
}
else
{
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
// First check if we are a differnet curosr...
if ( uiCursorIndex != guiOldSetCursor )
{
// OK, check if we are a delay cursor...
if ( pCurData->bFlags & DELAY_START_CURSOR )
{
guiDelayTimer = GetTickCount( );
}
}
guiOldSetCursor = uiCursorIndex;
// Olny update if delay timer has elapsed...
if ( pCurData->bFlags & DELAY_START_CURSOR )
{
if ( ( GetTickCount( ) - guiDelayTimer ) < 1000 )
{
EraseMouseCursor( );
SetMouseCursorProperties( 0, 0, 5, 5 );
DirtyCursor( );
return( TRUE );
}
}
//
// Call LoadCursorData to make sure that the video object is loaded
//
LoadCursorData(uiCursorIndex);
// Erase old cursor
EraseMouseCursor( );
// NOW ACCOMODATE COMPOSITE CURSORS
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
// Check if we are a flashing cursor!
if ( pCurData->bFlags & CURSOR_TO_FLASH )
{
if ( cnt <= 1 )
{
if ( pCurData->bFlashIndex != cnt )
{
continue;
}
}
}
// Check if we are a sub cursor!
// IN this case, do all frames but
// skip the 1st or second!
if ( pCurData->bFlags & CURSOR_TO_SUB_CONDITIONALLY )
{
if ( pCurData->bFlags & CURSOR_TO_FLASH )
{
if ( cnt <= 1 )
{
if ( pCurData->bFlashIndex != cnt )
{
continue;
}
}
}
else if ( pCurData->bFlags & CURSOR_TO_FLASH2 )
{
if ( cnt <= 2 && cnt > 0 )
{
if ( pCurData->bFlashIndex != cnt )
{
continue;
}
}
}
else
{
if ( cnt <= 1 )
{
if ( pCurData->bFlashIndex != cnt )
{
continue;
}
}
}
}
pCurImage = &( pCurData->Composites[ cnt ] );
// Adjust sub-index if cursor is animated
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex].ubFlags & ANIMATED_CURSOR )
{
usSubIndex = (UINT16)pCurImage->uiCurrentFrame;
}
else
{
usSubIndex = pCurImage->uiSubIndex;
}
if ( pCurImage->usPosX != HIDE_SUBCURSOR && pCurImage->usPosY != HIDE_SUBCURSOR )
{
// Blit cursor at position in mouse buffer
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex].ubFlags & USE_OUTLINE_BLITTER )
{
ReturnValue = BltToMouseCursorFromVObjectWithOutline( gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject , usSubIndex, pCurImage->usPosX, pCurImage->usPosY );
}
else
{
ReturnValue = BltToMouseCursorFromVObject( gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject , usSubIndex, pCurImage->usPosX, pCurImage->usPosY );
}
if ( !ReturnValue )
{
return( FALSE );
}
}
//if ( pCurData->bFlags & CURSOR_TO_FLASH )
//{
// break;
//}
}
// Hook into hook function
if ( gMouseBltOverride != NULL )
{
gMouseBltOverride( );
}
sCenterValX = pCurData->sOffsetX;
sCenterValY = pCurData->sOffsetY;
SetMouseCursorProperties( sCenterValX, (INT16)( sCenterValY + gsGlobalCursorYOffset ), pCurData->usHeight, pCurData->usWidth );
DirtyCursor( );
}
}
}
else
{
if ( uiCursorIndex == VIDEO_NO_CURSOR )
{
EraseMouseCursor( );
SetMouseCursorProperties( 0, 0, 5, 5 );
DirtyCursor( );
//EnableCursor( FALSE );
}
else
{
SetCurrentCursor( (UINT16)uiCursorIndex, 0, 0 );
ReturnValue = TRUE;
}
}
return ( ReturnValue );
}
void SetMouseBltHook( MOUSEBLT_HOOK pMouseBltOverride )
{
gMouseBltOverride = pMouseBltOverride;
}
// Sets an external video object as cursor file data....
void SetExternVOData( UINT32 uiCursorIndex, HVOBJECT hVObject, UINT16 usSubIndex )
{
CursorData *pCurData;
CursorImage *pCurImage;
UINT32 cnt;
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
pCurImage = &( pCurData->Composites[ cnt ] );
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFlags & USE_EXTERN_VO_CURSOR )
{
// OK, set Video Object here....
// If loaded, unload...
UnLoadCursorData( uiCursorIndex );
// Set extern vo
gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject = hVObject;
pCurImage->uiSubIndex = usSubIndex;
// Reload....
LoadCursorData( uiCursorIndex );
}
}
}
void RemoveExternVOData( UINT32 uiCursorIndex )
{
CursorData *pCurData;
CursorImage *pCurImage;
UINT32 cnt;
pCurData = &( gpCursorDatabase[ uiCursorIndex ] );
for ( cnt = 0; cnt < pCurData->usNumComposites; cnt++ )
{
pCurImage = &( pCurData->Composites[ cnt ] );
if ( gpCursorFileDatabase[ pCurImage->uiFileIndex ].ubFlags & USE_EXTERN_VO_CURSOR )
{
gpCursorFileDatabase[ pCurImage->uiFileIndex ].hVObject = NULL;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////