mirror of
https://github.com/electronicarts/CnC_Red_Alert.git
synced 2025-12-16 07:31:39 -05:00
Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
609
WIN32LIB/DRAWBUFF/ICONCACH.CPP
Normal file
609
WIN32LIB/DRAWBUFF/ICONCACH.CPP
Normal file
@@ -0,0 +1,609 @@
|
||||
/*
|
||||
** Command & Conquer Red Alert(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Drawbuff - Westwood win95 library *
|
||||
* *
|
||||
* File Name : Iconcach.CPP *
|
||||
* *
|
||||
* Programmer : Steve Tall *
|
||||
* *
|
||||
* Start Date : November 8th, 1995 *
|
||||
* *
|
||||
* Last Update : November 13th, 1995 [ST] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Overview: This file cantains members of the IconCacheClass and associated non member *
|
||||
* functions. All functions are to do with caching individual icons from icon sets *
|
||||
* into video memory to improve the speed of subsequent drawing *
|
||||
* *
|
||||
* Functions: *
|
||||
* Cache_New_Icon -- Call the Cache_It member to cache a registered icon to video memory *
|
||||
* Invalidate_Cached_Icons -- Uncache all the icons *
|
||||
* Restore_Cached_Icons -- restore cached icons after a focus loss *
|
||||
* Register_Icon_Set -- register an icon set as cachable *
|
||||
* Get_Free_Cache_Slot -- find an empty cache slot *
|
||||
* IconCacheClass::IconCacheClass -- IconCacheClass constructor *
|
||||
* IconCacheClass::~IconCacheClass -- IconCacheClass destructor *
|
||||
* IconCacheClass::Restore -- restore the icons surface and recache it *
|
||||
* IconCacheClass::Cache_It -- cache an icon into video memory *
|
||||
* IconCacheClass::Uncache_It -- restore the video memory used by a cached icon *
|
||||
* IconCacheClass::Draw_It -- use the blitter to draw the cached icon *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include "ddraw.h"
|
||||
#include "misc.h"
|
||||
#include "iconcach.h"
|
||||
#include "gbuffer.h"
|
||||
|
||||
|
||||
static DDSURFACEDESC VideoSurfaceDescription;
|
||||
|
||||
IconCacheClass CachedIcons[MAX_CACHED_ICONS];
|
||||
|
||||
extern "C"{
|
||||
IconSetType IconSetList[MAX_ICON_SETS];
|
||||
short IconCacheLookup[MAX_LOOKUP_ENTRIES];
|
||||
}
|
||||
|
||||
int CachedIconsDrawn=0; //Counter of number of cache hits
|
||||
int UnCachedIconsDrawn=0; //Counter of number of cache misses
|
||||
BOOL CacheMemoryExhausted; //Flag set if we have run out of video RAM
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Optimise_Video_Memory_Cache -- optimises usage of video memory *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: TRUE if memory was freed up *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/29/95 12:47PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL Optimize_Video_Memory_Cache (void)
|
||||
{
|
||||
|
||||
if (CacheMemoryExhausted &&
|
||||
(UnCachedIconsDrawn+CachedIconsDrawn > 1000) &&
|
||||
UnCachedIconsDrawn > CachedIconsDrawn){
|
||||
|
||||
int cache_misses[MAX_CACHED_ICONS];
|
||||
int cache_hits[MAX_CACHED_ICONS];
|
||||
int total_cache_misses=0;
|
||||
int total_cache_hits=0;
|
||||
int counter;
|
||||
int i;
|
||||
int j;
|
||||
int temp;
|
||||
BOOL swapped;
|
||||
|
||||
/*
|
||||
** make list of icons that have failed to cache more than 5 times
|
||||
*/
|
||||
for (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){
|
||||
|
||||
if (CachedIcons[counter].TimesFailed>5){
|
||||
cache_misses[total_cache_misses++] = counter;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Make list of icons that have been drawn less than 3 times
|
||||
*/
|
||||
for (counter=0 ; counter<MAX_CACHED_ICONS ; counter++){
|
||||
|
||||
if (CachedIcons[counter].TimesDrawn<3){
|
||||
cache_hits[total_cache_hits++] = counter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Sort drawn icons into order
|
||||
*/
|
||||
if (total_cache_hits > 1){
|
||||
for (i = 0 ; i<total_cache_hits ; i++){
|
||||
swapped=FALSE;
|
||||
for (j=0 ; j<total_cache_hits-1 ; j++){
|
||||
|
||||
if (CachedIcons[cache_hits[j]].TimesDrawn > CachedIcons[cache_hits[j+1]].TimesDrawn){
|
||||
temp=cache_hits[j];
|
||||
cache_hits[j]=cache_hits[j+1];
|
||||
cache_hits[j+1]=temp;
|
||||
swapped = TRUE;
|
||||
}
|
||||
}
|
||||
if (!swapped) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Uncache icons up to the number of failed icons
|
||||
*/
|
||||
|
||||
for (counter=0 ; counter<total_cache_misses && counter<total_cache_hits; counter++){
|
||||
CachedIcons[cache_hits[counter]].Uncache_It();
|
||||
}
|
||||
|
||||
CacheMemoryExhausted=FALSE;
|
||||
CachedIconsDrawn=0;
|
||||
UnCachedIconsDrawn=0;
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Cache_New_Icon -- cache a registered icon to video memory *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: icon_index -- index into registered icon table of icon to cache *
|
||||
* icon_ptr -- ptr to icon data *
|
||||
* *
|
||||
* OUTPUT: BOOL success *
|
||||
* *
|
||||
* WARNINGS: icon must already have been registered and assigned an index *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:36AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL Cache_New_Icon (int icon_index, void *icon_ptr)
|
||||
{
|
||||
if (!CacheMemoryExhausted){
|
||||
return (CachedIcons[icon_index].Cache_It(icon_ptr));
|
||||
} else {
|
||||
CachedIcons[icon_index].TimesFailed++;
|
||||
if (Optimize_Video_Memory_Cache()){
|
||||
return (CachedIcons[icon_index].Cache_It(icon_ptr));
|
||||
} else {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Invalidat_Cached_Icons -- used to release any icons that have been cached *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:37AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void Invalidate_Cached_Icons (void)
|
||||
{
|
||||
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
|
||||
CachedIcons[i].Uncache_It();
|
||||
}
|
||||
|
||||
memset (&IconCacheLookup[0] , -1 ,MAX_LOOKUP_ENTRIES*sizeof(IconCacheLookup[0]));
|
||||
|
||||
for (i=0 ; i<MAX_ICON_SETS ; i++){
|
||||
IconSetList[i].IconSetPtr=NULL;
|
||||
}
|
||||
|
||||
CacheMemoryExhausted=FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Restore_Cached_Icons -- re-cache icons into video memory after a loss of focus *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: Assumes that the pointers that were originally used to cache the icons *
|
||||
* are still valid. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:38AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void Restore_Cached_Icons (void)
|
||||
{
|
||||
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
|
||||
CachedIcons[i].Restore();
|
||||
}
|
||||
CacheMemoryExhausted=FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Register_Icon_Set -- used to register an icon set as cachable *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: icon_data - ptr to icon set *
|
||||
* pre_cache -- should we pre-cache the icon data? *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:39AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void Register_Icon_Set (void *icon_data , BOOL pre_cache)
|
||||
{
|
||||
|
||||
for (int i=0 ; i<MAX_ICON_SETS ; i++){
|
||||
if (!IconSetList[i].IconSetPtr){
|
||||
IconSetList[i].IconSetPtr = (IControl_Type*)icon_data;
|
||||
|
||||
if (i){
|
||||
IControl_Type *previous_set = IconSetList[i-1].IconSetPtr;
|
||||
IconSetList[i].IconListOffset = IconSetList[i-1].IconListOffset + ((int)previous_set->Count)*2;
|
||||
if (IconSetList[i].IconListOffset > MAX_LOOKUP_ENTRIES*2){
|
||||
IconSetList[i].IconSetPtr = NULL;
|
||||
}
|
||||
} else {
|
||||
IconSetList[i].IconListOffset = 0;
|
||||
}
|
||||
|
||||
if (pre_cache){
|
||||
for (i=0 ; i<256 ; i++){
|
||||
Is_Icon_Cached(icon_data,i);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* Get_Free_Cache_Slot -- find a free slot in which to cache an icon *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: int - icon index *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:40AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
int Get_Free_Cache_Slot (void)
|
||||
{
|
||||
for (int i=0 ; i<MAX_CACHED_ICONS ; i++){
|
||||
if (!CachedIcons[i].Get_Is_Cached()){
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::IconCacheClass -- constructor for icon cache class *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:41AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
IconCacheClass::IconCacheClass (void)
|
||||
{
|
||||
IsCached =FALSE;
|
||||
SurfaceLost =FALSE;
|
||||
DrawFrequency =0;
|
||||
CacheSurface =NULL;
|
||||
IconSource =NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::~IconCacheClass -- destructor for icon cache class *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:41AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
IconCacheClass::~IconCacheClass (void)
|
||||
{
|
||||
if (IsCached && CacheSurface){
|
||||
CacheSurface->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::Restore -- Restores the icons video surface memory and reloads it based on the original*
|
||||
* icon pointer *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: Relies on the icons original pointer still being valie *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:43AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void IconCacheClass::Restore (void)
|
||||
{
|
||||
if (IsCached && CacheSurface){
|
||||
CacheSurface->Restore();
|
||||
if (IconSource){
|
||||
Cache_It(IconSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::Cache_It -- allocate video memory and copy an icon to it *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: icon_ptr -- ptr to icon data *
|
||||
* *
|
||||
* OUTPUT: bool -- success? *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:44AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
BOOL IconCacheClass::Cache_It (void *icon_ptr)
|
||||
{
|
||||
DDSCAPS surface_capabilities;
|
||||
BOOL return_value;
|
||||
|
||||
/*
|
||||
** If we dont have a direct draw interface yet then just fail
|
||||
*/
|
||||
if (!DirectDrawObject) return(FALSE);
|
||||
|
||||
/*
|
||||
** Set up the description of the surface we want to create
|
||||
*/
|
||||
memset (&VideoSurfaceDescription , 0 , sizeof ( VideoSurfaceDescription ));
|
||||
|
||||
VideoSurfaceDescription.dwSize = sizeof( VideoSurfaceDescription );
|
||||
VideoSurfaceDescription.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||||
VideoSurfaceDescription.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
||||
VideoSurfaceDescription.dwHeight = ICON_WIDTH;
|
||||
VideoSurfaceDescription.dwWidth = ICON_HEIGHT;
|
||||
|
||||
/*
|
||||
** If this cache object doesnt already have a surface then create one
|
||||
*/
|
||||
if (!CacheSurface){
|
||||
if (DD_OK!=DirectDrawObject->CreateSurface( &VideoSurfaceDescription , &CacheSurface , NULL)){
|
||||
CacheMemoryExhausted = TRUE;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** Make sure the surface we created isnt really in system memory
|
||||
*/
|
||||
if (DD_OK != CacheSurface->GetCaps(&surface_capabilities)){
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if ((DDSCAPS_SYSTEMMEMORY & surface_capabilities.dwCaps) == DDSCAPS_SYSTEMMEMORY){
|
||||
CacheSurface->Release();
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return_value=FALSE;
|
||||
/*
|
||||
** Lock the surface so we can copy the icon to it
|
||||
*/
|
||||
if (DD_OK== CacheSurface->Lock ( NULL
|
||||
, &(VideoSurfaceDescription)
|
||||
, DDLOCK_WAIT
|
||||
, NULL)){
|
||||
/*
|
||||
** Copy the icon to the surface and flag that icon is cached
|
||||
*/
|
||||
Cache_Copy_Icon (icon_ptr , VideoSurfaceDescription.lpSurface , VideoSurfaceDescription.lPitch);
|
||||
IsCached=TRUE;
|
||||
SurfaceLost=FALSE;
|
||||
IconSource=icon_ptr;
|
||||
return_value=TRUE;
|
||||
}
|
||||
CacheSurface->Unlock(NULL);
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::Uncache_It -- release the video memory used to cache an icon *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:48AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void IconCacheClass::Uncache_It(void)
|
||||
{
|
||||
|
||||
if (IsCached && CacheSurface){
|
||||
CacheSurface->Release();
|
||||
IsCached=FALSE;
|
||||
CacheSurface=NULL;
|
||||
IconSource=NULL;
|
||||
CacheMemoryExhausted=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* ICC::Draw_It -- use the blitter to draw a cached icon *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: surface to draw to *
|
||||
* x coord to draw to (relative to window) *
|
||||
* y coord to draw to (relative to window) *
|
||||
* window left coord *
|
||||
* window top coord *
|
||||
* window width *
|
||||
* window height *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/13/95 9:48AM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void IconCacheClass::Draw_It (LPDIRECTDRAWSURFACE dest_surface , int x_pixel, int y_pixel, int window_left , int window_top , int window_width , int window_height)
|
||||
{
|
||||
RECT source_rectangle;
|
||||
RECT dest_rectangle;
|
||||
int clip;
|
||||
HRESULT return_code;
|
||||
|
||||
/*
|
||||
** Set up the source and destination coordinates as required by direct draw
|
||||
*/
|
||||
source_rectangle.left = 0;
|
||||
source_rectangle.top = 0;
|
||||
source_rectangle.right = ICON_WIDTH;
|
||||
source_rectangle.bottom = ICON_HEIGHT;
|
||||
|
||||
dest_rectangle.left = window_left+x_pixel;
|
||||
dest_rectangle.top = window_top+y_pixel;
|
||||
dest_rectangle.right = dest_rectangle.left+ICON_WIDTH;
|
||||
dest_rectangle.bottom = dest_rectangle.top+ICON_HEIGHT;
|
||||
|
||||
/*
|
||||
** Clip the coordinates to the window
|
||||
*/
|
||||
if (dest_rectangle.left<window_left){
|
||||
source_rectangle.left += window_left-dest_rectangle.left;
|
||||
dest_rectangle.left=window_left;
|
||||
}
|
||||
|
||||
if (dest_rectangle.right>=window_left+window_width){
|
||||
clip = dest_rectangle.right-(window_left+window_width);
|
||||
source_rectangle.right -= clip;
|
||||
dest_rectangle.right -= clip;
|
||||
}
|
||||
|
||||
if (dest_rectangle.top<window_top){
|
||||
source_rectangle.top += window_top-dest_rectangle.top;
|
||||
dest_rectangle.top=window_top;
|
||||
}
|
||||
|
||||
if (dest_rectangle.bottom>=window_top+window_height){
|
||||
clip = dest_rectangle.bottom-(window_top+window_height);
|
||||
source_rectangle.bottom -= clip;
|
||||
dest_rectangle.bottom -= clip;
|
||||
}
|
||||
|
||||
if (source_rectangle.left>=source_rectangle.right){
|
||||
return;
|
||||
}
|
||||
|
||||
if (source_rectangle.top>=source_rectangle.bottom){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Do the blit
|
||||
*/
|
||||
return_code = dest_surface->Blt (&dest_rectangle ,
|
||||
CacheSurface ,
|
||||
&source_rectangle ,
|
||||
DDBLT_WAIT |
|
||||
DDBLT_ASYNC ,
|
||||
NULL);
|
||||
|
||||
if (return_code == DDERR_SURFACELOST && Gbuffer_Focus_Loss_Function){
|
||||
Gbuffer_Focus_Loss_Function();
|
||||
}
|
||||
|
||||
if ( return_code != DDERR_SURFACELOST && return_code != DD_OK ) {
|
||||
char temp[100];
|
||||
sprintf(temp,"DD Error code %d\n", return_code & 0xFFFF);
|
||||
OutputDebugString(temp);
|
||||
}
|
||||
|
||||
TimesDrawn++;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user