610 lines
28 KiB
C++
610 lines
28 KiB
C++
![]() |
/*
|
||
|
** 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++;
|
||
|
|
||
|
}
|
||
|
|