I have followed John’s advice and I have created a test version of my
functions (included bellow). It helped me to track down the main problem
to the SDL_DisplayFormat() function in LoadIMG().
It looks like this portion is:
// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}
return ready;
}
Obviously I should destroy the surface “ready” but I don’t now how (in
this context). SDL_GetError returnes Out of memory.
And the other problems still remains. If I run the program twice on
Win98 the transparent color of the “splashImage” image is not
transparent the second time. The problem seems to be the SDL_HWPALETTE
flag in fullscreen mode (under Win98 only).
BTW I have removed ready = SDL_DisplayFormat( temp ); and it takes now
longer to crash under Win98 (under NT seems that it won’t crash).
Well, not the question might be: how to use correctly SDL_HWPALETTE and
SDL_DisplayFormat
// PVTest.cpp : Defines the entry point for the console application.
// Do not show splash
//#define NOSPLASH
// Data defines
#define MAX_IMAGES 10
#define SPLASH “./data/splash/splash.gif”
// Image collection 1
#define IMAGE0101 “./data/set01/01.jpg”
#define IMAGE0102 “./data/set01/02.jpg”
#define IMAGE0103 “./data/set01/03.jpg”
#define IMAGE0104 “./data/set01/04.jpg”
#define IMAGE0105 “./data/set01/05.jpg”
#define IMAGE0106 “./data/set01/06.jpg”
#define IMAGE0107 “./data/set01/07.jpg”
#define IMAGE0108 “./data/set01/08.jpg”
#define IMAGE0109 “./data/set01/09.jpg”
#define IMAGE0110 “./data/set01/10.jpg”
// Image collection 2
#define IMAGE0201 “./data/set02/01.jpg”
#define IMAGE0202 “./data/set02/02.jpg”
#define IMAGE0203 “./data/set02/03.jpg”
#define IMAGE0204 “./data/set02/04.jpg”
#define IMAGE0205 “./data/set02/05.jpg”
#define IMAGE0206 “./data/set02/06.jpg”
#define IMAGE0207 “./data/set02/07.jpg”
#define IMAGE0208 “./data/set02/08.jpg”
#define IMAGE0209 “./data/set02/09.jpg”
#define IMAGE0210 “./data/set02/10.jpg”
//////////////////////////////////////////////////////////
// Headers
//////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
// SDL headers
#include “SDL/SDL.h”
#include “SDL/SDL_image.h”
// Structs
struct ColorRGB
{
int r;
int g;
int b;
};
//////////////////////////////////////////////////////////
// System variables
//////////////////////////////////////////////////////////
// Main video surface
SDL_Surface *screen = NULL;
// Video mode
#ifdef _DEBUG
int videoResolutionWidth = 640;
int videoResolutionHeight = 480;
int videoBitDepth = 0;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF
#else
int videoResolutionWidth = 1024;
int videoResolutionHeight = 768;
int videoBitDepth = 32;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF |
SDL_FULLSCREEN
#endif
//////////////////////////////////////////////////////////
// Variables
//////////////////////////////////////////////////////////
// Surfaces
SDL_Surface *splashImage;
SDL_Surface *images[ 15 ];
// Events
SDL_Event event;
// Game variables
bool done = false;
bool currentSet = false;
int currentImage = MAX_IMAGES;
int imageAdvanceTime = 7000;
//////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////
void ClearScreen()
{
SDL_Rect destination;
// Calculate screen size
destination.x = 0;
destination.y = 0;
destination.w = screen->w;
destination.h = screen->h;
// clear screen
SDL_FillRect( screen, &destination, 0 );
}
//////////////////////////////////////////////////////////
// Loaders
//////////////////////////////////////////////////////////
// Loads .JPG image with SDL_Image calls
SDL_Surface *LoadIMG( char *FileName, ColorRGB transparentColor )
{
SDL_Surface *temp = NULL;
SDL_Surface *ready = NULL;
// Load image with SDL_image call
temp = IMG_Load( FileName );
if( temp == NULL )
{
printf( “Image file load failed: %s\n”,
IMG_GetError()
);
exit( 2 );
}
// Set transparent color for this surface (image)
if ( SDL_SetColorKey( temp, SDL_SRCCOLORKEY,
SDL_MapRGB( temp->format,
transparentColor.r,
transparentColor.g,
transparentColor.b
)
) == -1 )
printf( “Failed to set transparent color: %s\n”,
SDL_GetError()
);
// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}
return ready;
}
void LoadImageSet01()
{
for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;
// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
}
void LoadImageSet02()
{
for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;
// Load images
images[ 0 ] = LoadIMG( IMAGE0201, transparent );
images[ 1 ] = LoadIMG( IMAGE0202, transparent );
images[ 2 ] = LoadIMG( IMAGE0203, transparent );
images[ 3 ] = LoadIMG( IMAGE0204, transparent );
images[ 4 ] = LoadIMG( IMAGE0205, transparent );
images[ 5 ] = LoadIMG( IMAGE0206, transparent );
images[ 6 ] = LoadIMG( IMAGE0207, transparent );
images[ 7 ] = LoadIMG( IMAGE0208, transparent );
images[ 8 ] = LoadIMG( IMAGE0209, transparent );
images[ 9 ] = LoadIMG( IMAGE0210, transparent );
}
#ifndef NOSPLASH
void LoadSplash()
{
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;
splashImage = LoadIMG( SPLASH, transparent );
}
#endif
//////////////////////////////////////////////////////////
// Initializers and de-initializers
//////////////////////////////////////////////////////////
// Initializes all SDL subsystems
void InitAll()
{
// Initialize SDL - Video and Timer subsystems
if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
{
fprintf( stderr,
“Couldn’t initialize SDL: %s\n”,
SDL_GetError()
);
exit( 1 );
}
// Hide cursor
#ifndef _DEBUG
if ( SDL_ShowCursor( SDL_DISABLE ) == - 1)
{
fprintf( stderr,
“Couldn’t hide the cursor: %s\n”,
SDL_GetError()
);
}
#endif
// Initialize display mode
screen = SDL_SetVideoMode( videoResolutionWidth,
videoResolutionHeight,
videoBitDepth,
videoModeFlags
);
if ( screen == NULL )
{
printf(“Couldn’t initialize 640x480x32 video mode: %s\n”,
SDL_GetError());
exit( 1 );
}
}
// Quits all SDL subsystems
void QuitAll()
{
SDL_Quit();
}
void LoadMedia()
{
#ifndef NOSPLASH
LoadSplash();
#endif
LoadImageSet01();
}
void UnloadMedia()
{
for ( int index = 0; index < 15; index ++ )
if ( images[ index ] != NULL )
{
SDL_FreeSurface( images[ index ] );
}
}
//////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////
void UpdateScreen()
{
ClearScreen();
SDL_Rect destination;
// Calculate image size
destination.x = screen->w / 2 - images[ currentImage ]->w / 2;
destination.y = screen->h / 2 - images[ currentImage ]->h / 2;
destination.w = images[ currentImage ]->w;
destination.h = images[ currentImage ]->h;
// Blit image
SDL_BlitSurface ( images[ currentImage ], NULL, screen, &destination );
#ifndef NOSPLASH
// Calculate image size
destination.x = screen->w / 2 - splashImage->w / 2;
destination.y = screen->h / 2 - splashImage->h / 2;
destination.w = splashImage->w;
destination.h = splashImage->h;
SDL_BlitSurface( splashImage, NULL, screen, &destination);
#endif
SDL_Flip( screen );
}
void ImageSequenceAdvance( bool Forward )
//SDL_NewTimerCallBack ImageSequenceAdvance( bool Forward )
{
if ( Forward )
{
currentImage++;
if ( currentImage > MAX_IMAGES - 1 )
currentImage = 0;
}
else
{
currentImage–;
if ( currentImage < 0 )
currentImage = MAX_IMAGES - 1;
}
}
void TimedImageSequenceAdvance( int Interval )
{
static Uint32 next_time = 0;
Uint32 now;
now = SDL_GetTicks();
if ( next_time <= now ) {
next_time = now + Interval;
ImageSequenceAdvance( true );
}
}
// The Game Loop
void Run()
{
while( !done )
{
TimedImageSequenceAdvance( imageAdvanceTime );
UpdateScreen();
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
// Select manually next image
case SDLK_LEFT:
ImageSequenceAdvance( false );
break;
case SDLK_RIGHT:
ImageSequenceAdvance( true );
break;
// Select next image set
case SDLK_UP:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
case SDLK_DOWN:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
// Quit if user presses Escape
case SDLK_ESCAPE:
done = true;
break;
default:
break;
}
break;
// Quit if QUIT event is intercepted
case SDL_QUIT:
done = true;
break;
default:
break;
}
}
// Allow other threads to run
SDL_Delay( 10 );
}
}
int main(int argc, char* argv[])
{
InitAll();
LoadMedia();
SDL_Delay( 1000 );
// Run the “Game” Loop
Run();
// Clean up before exit
UnloadMedia();
QuitAll();
return 0;
}