2007-01-15 12:09:25 -08:00
|
|
|
/*
|
|
|
|
This file is part of Warzone 2100.
|
|
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
|
|
Copyright (C) 2005-2007 Warzone Resurrection Project
|
|
|
|
|
|
|
|
Warzone 2100 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 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Warzone 2100 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 Warzone 2100; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Frame.c
|
|
|
|
*
|
|
|
|
* Initialisation and shutdown for the framework library.
|
|
|
|
*
|
|
|
|
* Includes a basic windows message loop.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// defines the inline functions in this module
|
|
|
|
#define DEFINE_INLINE
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
2006-11-06 06:40:07 -08:00
|
|
|
#include <string.h>
|
2007-06-28 10:47:08 -07:00
|
|
|
#include <SDL/SDL.h>
|
|
|
|
#include <physfs.h>
|
|
|
|
|
2006-02-18 10:54:37 -08:00
|
|
|
// window focus messages
|
2007-06-28 10:47:08 -07:00
|
|
|
//#define DEBUG_GROUP1
|
|
|
|
#include "frame.h"
|
|
|
|
#include "frameint.h"
|
2006-09-23 11:38:12 -07:00
|
|
|
#include "frameresource.h"
|
2006-09-23 11:40:07 -07:00
|
|
|
#include "input.h"
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
#include "fractions.h"
|
|
|
|
#include <assert.h>
|
2006-08-12 03:45:49 -07:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#include "cursors16.h"
|
|
|
|
#else
|
2006-08-06 17:52:01 -07:00
|
|
|
#include "cursors.h"
|
2006-08-12 03:45:49 -07:00
|
|
|
#endif
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-07-05 13:39:13 -07:00
|
|
|
#include "SDL_framerate.h"
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
#define IGNORE_FOCUS
|
|
|
|
|
|
|
|
/* Linux specific stuff */
|
|
|
|
|
2006-07-05 13:39:13 -07:00
|
|
|
static FPSmanager wzFPSmanager;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
static UWORD currentCursorResID = UWORD_MAX;
|
2007-06-28 10:47:08 -07:00
|
|
|
SDL_Cursor *aCursors[MAX_CURSORS];
|
|
|
|
|
|
|
|
typedef enum _focus_state
|
|
|
|
{
|
|
|
|
FOCUS_OUT, // Window does not have the focus
|
|
|
|
FOCUS_SET, // Just received WM_SETFOCUS
|
|
|
|
FOCUS_IN, // Window has got the focus
|
|
|
|
FOCUS_KILL, // Just received WM_KILLFOCUS
|
|
|
|
} FOCUS_STATE;
|
|
|
|
|
|
|
|
FOCUS_STATE focusState, focusLast;
|
|
|
|
|
|
|
|
/************************************************************************************
|
|
|
|
*
|
|
|
|
* Alex's frame rate stuff
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Over how many seconds is the average required? */
|
|
|
|
#define TIMESPAN 5
|
|
|
|
|
|
|
|
/* Initial filler value for the averages - arbitrary */
|
|
|
|
#define IN_A_FRAME 70
|
|
|
|
|
|
|
|
/* Global variables for the frame rate stuff */
|
2006-08-27 12:01:34 -07:00
|
|
|
static Uint32 FrameCounts[TIMESPAN] = { 0 };
|
|
|
|
static Uint32 FrameIndex = 0;
|
|
|
|
static Uint64 curFrames = 0; // Number of frames elapsed since start
|
|
|
|
static Uint64 lastFrames = 0;
|
|
|
|
static Uint32 curTicks = 0; // Number of ticks since execution started
|
|
|
|
static Uint32 lastTicks = 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/* InitFrameStuff - needs to be called once before frame loop commences */
|
|
|
|
static void InitFrameStuff( void )
|
|
|
|
{
|
2006-08-27 12:01:34 -07:00
|
|
|
UDWORD i;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
for (i=0; i<TIMESPAN; i++)
|
2006-08-27 12:01:34 -07:00
|
|
|
{
|
2007-06-28 10:47:08 -07:00
|
|
|
FrameCounts[i] = IN_A_FRAME;
|
2006-08-27 12:01:34 -07:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
FrameIndex = 0;
|
2006-08-27 12:01:34 -07:00
|
|
|
curFrames = 0;
|
|
|
|
lastFrames = 0;
|
|
|
|
curTicks = 0;
|
|
|
|
lastTicks = 0;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* MaintainFrameStuff - call this during completion of each frame loop */
|
|
|
|
static void MaintainFrameStuff( void )
|
|
|
|
{
|
2006-08-27 12:01:34 -07:00
|
|
|
curTicks = SDL_GetTicks();
|
|
|
|
curFrames++;
|
|
|
|
|
|
|
|
// Update the framerate only once per second
|
|
|
|
if ( curTicks >= lastTicks + 1000 )
|
|
|
|
{
|
|
|
|
// TODO Would have to be normalized to be correct for < 1 fps:
|
|
|
|
// FrameCounts[FrameIndex++] = 1000 * (curFrames - lastFrames) / (curTicks - lastTicks);
|
|
|
|
FrameCounts[FrameIndex++] = curFrames - lastFrames;
|
|
|
|
if ( FrameIndex >= TIMESPAN )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
FrameIndex = 0;
|
|
|
|
}
|
2006-08-27 12:01:34 -07:00
|
|
|
lastTicks = curTicks;
|
|
|
|
lastFrames = curFrames;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-27 12:01:34 -07:00
|
|
|
UDWORD frameGetAverageRate(void)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-08-27 12:01:34 -07:00
|
|
|
SDWORD averageFrames = 0, i = 0;
|
|
|
|
for ( i = 0; i < TIMESPAN; i++ )
|
|
|
|
averageFrames += FrameCounts[i];
|
|
|
|
averageFrames /= TIMESPAN;
|
|
|
|
|
|
|
|
return averageFrames;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
2006-08-27 12:01:34 -07:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
UDWORD frameGetFrameNumber(void)
|
|
|
|
{
|
2006-08-27 12:01:34 -07:00
|
|
|
return curFrames;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Set the current cursor from a Resource ID */
|
2006-11-03 17:11:26 -08:00
|
|
|
void frameSetCursorFromRes(SWORD resID)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-08-23 05:58:48 -07:00
|
|
|
ASSERT( resID >= CURSOR_OFFSET, "frameSetCursorFromRes: bad resource ID" );
|
|
|
|
ASSERT( resID < CURSOR_OFFSET + MAX_CURSORS, "frameSetCursorFromRes: bad resource ID" );
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
//If we are already using this cursor then return
|
|
|
|
if (resID != currentCursorResID)
|
|
|
|
{
|
|
|
|
SDL_SetCursor(aCursors[resID - CURSOR_OFFSET]);
|
|
|
|
currentCursorResID = resID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-31 12:29:24 -08:00
|
|
|
void setFramerateLimit(Uint32 fpsLimit)
|
|
|
|
{
|
|
|
|
SDL_setFramerate( &wzFPSmanager, fpsLimit );
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 getFramerateLimit(void)
|
|
|
|
{
|
|
|
|
return SDL_getFramerate( &wzFPSmanager );
|
|
|
|
}
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/*
|
2006-11-03 17:11:26 -08:00
|
|
|
* processEvent
|
2007-06-28 10:47:08 -07:00
|
|
|
*
|
2006-11-03 17:11:26 -08:00
|
|
|
* Event processing function
|
2007-06-28 10:47:08 -07:00
|
|
|
*/
|
|
|
|
static void processEvent(SDL_Event *event)
|
|
|
|
{
|
|
|
|
switch(event->type)
|
|
|
|
{
|
|
|
|
#ifndef IGNORE_FOCUS
|
|
|
|
case SDL_ACTIVEEVENT:
|
|
|
|
if (event->active.state == SDL_APPINPUTFOCUS || event->active.state == SDL_APPACTIVE)
|
|
|
|
{
|
|
|
|
if (event->active.gain == 1)
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "WM_SETFOCUS\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
if (focusState != FOCUS_IN)
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "FOCUS_SET\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
focusState = FOCUS_SET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "WM_KILLFOCUS\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
if (focusState != FOCUS_OUT)
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "FOCUS_KILL\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
focusState = FOCUS_KILL;
|
|
|
|
}
|
|
|
|
/* Have to tell the input system that we've lost focus */
|
|
|
|
inputProcessEvent(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case SDL_KEYUP:
|
|
|
|
case SDL_KEYDOWN:
|
|
|
|
case SDL_MOUSEBUTTONUP:
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
|
|
case SDL_MOUSEMOTION:
|
|
|
|
inputProcessEvent(event);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-09-13 02:09:05 -07:00
|
|
|
static void initCursors(void)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
aCursors[CURSOR_ARROW - CURSOR_OFFSET] = init_system_cursor(cursor_arrow);
|
|
|
|
aCursors[CURSOR_DEST - CURSOR_OFFSET] = init_system_cursor(cursor_dest);
|
|
|
|
aCursors[CURSOR_SIGHT - CURSOR_OFFSET] = init_system_cursor(cursor_sight);
|
|
|
|
aCursors[CURSOR_TARGET - CURSOR_OFFSET] = init_system_cursor(cursor_target);
|
|
|
|
aCursors[CURSOR_LARROW - CURSOR_OFFSET] = init_system_cursor(cursor_larrow);
|
|
|
|
aCursors[CURSOR_RARROW - CURSOR_OFFSET] = init_system_cursor(cursor_rarrow);
|
|
|
|
aCursors[CURSOR_DARROW - CURSOR_OFFSET] = init_system_cursor(cursor_darrow);
|
|
|
|
aCursors[CURSOR_UARROW - CURSOR_OFFSET] = init_system_cursor(cursor_uarrow);
|
|
|
|
aCursors[CURSOR_DEFAULT - CURSOR_OFFSET] = init_system_cursor(cursor_default);
|
|
|
|
aCursors[CURSOR_EDGEOFMAP - CURSOR_OFFSET] = init_system_cursor(cursor_default);
|
|
|
|
aCursors[CURSOR_ATTACH - CURSOR_OFFSET] = init_system_cursor(cursor_attach);
|
|
|
|
aCursors[CURSOR_ATTACK - CURSOR_OFFSET] = init_system_cursor(cursor_attack);
|
|
|
|
aCursors[CURSOR_BOMB - CURSOR_OFFSET] = init_system_cursor(cursor_bomb);
|
|
|
|
aCursors[CURSOR_BRIDGE - CURSOR_OFFSET] = init_system_cursor(cursor_bridge);
|
|
|
|
aCursors[CURSOR_BUILD - CURSOR_OFFSET] = init_system_cursor(cursor_build);
|
|
|
|
aCursors[CURSOR_EMBARK - CURSOR_OFFSET] = init_system_cursor(cursor_embark);
|
|
|
|
aCursors[CURSOR_FIX - CURSOR_OFFSET] = init_system_cursor(cursor_fix);
|
|
|
|
aCursors[CURSOR_GUARD - CURSOR_OFFSET] = init_system_cursor(cursor_guard);
|
|
|
|
aCursors[CURSOR_JAM - CURSOR_OFFSET] = init_system_cursor(cursor_jam);
|
|
|
|
aCursors[CURSOR_LOCKON - CURSOR_OFFSET] = init_system_cursor(cursor_lockon);
|
|
|
|
aCursors[CURSOR_MENU - CURSOR_OFFSET] = init_system_cursor(cursor_menu);
|
|
|
|
aCursors[CURSOR_MOVE - CURSOR_OFFSET] = init_system_cursor(cursor_move);
|
|
|
|
aCursors[CURSOR_NOTPOSSIBLE - CURSOR_OFFSET] = init_system_cursor(cursor_notpossible);
|
|
|
|
aCursors[CURSOR_PICKUP - CURSOR_OFFSET] = init_system_cursor(cursor_pickup);
|
|
|
|
aCursors[CURSOR_SEEKREPAIR - CURSOR_OFFSET] = init_system_cursor(cursor_seekrepair);
|
|
|
|
aCursors[CURSOR_SELECT - CURSOR_OFFSET] = init_system_cursor(cursor_select);
|
2006-02-18 10:54:37 -08:00
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
|
2006-09-13 02:09:05 -07:00
|
|
|
static void freeCursors(void)
|
2006-02-18 10:54:37 -08:00
|
|
|
{
|
|
|
|
unsigned int i = 0;
|
|
|
|
for( ; i < MAX_CURSORS; i++ )
|
|
|
|
{
|
|
|
|
SDL_FreeCursor( aCursors[i] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/*
|
|
|
|
* frameInitialise
|
|
|
|
*
|
|
|
|
* Initialise the framework library. - PC version
|
|
|
|
*/
|
2006-11-03 17:11:26 -08:00
|
|
|
BOOL frameInitialise(
|
|
|
|
const char *pWindowName,// The text to appear in the window title bar
|
|
|
|
UDWORD width, // The display width
|
|
|
|
UDWORD height, // The display height
|
|
|
|
UDWORD bitDepth, // The display bit depth
|
|
|
|
BOOL fullScreen // Whether to start full screen or windowed
|
|
|
|
)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-11-03 17:11:26 -08:00
|
|
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_CDROM) != 0)
|
|
|
|
{
|
|
|
|
debug( LOG_ERROR, "Error: Could not initialise SDL (%s).\n", SDL_GetError() );
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
SDL_WM_SetCaption(pWindowName, NULL);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
focusState = FOCUS_IN;
|
|
|
|
focusLast = FOCUS_IN;
|
|
|
|
|
|
|
|
/* Initialise the trig stuff */
|
|
|
|
if (!trigInitialise())
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialise all cursors */
|
|
|
|
initCursors();
|
|
|
|
|
|
|
|
/* Initialise the Direct Draw Buffers */
|
2006-11-03 17:11:26 -08:00
|
|
|
if (!screenInitialise(width, height, bitDepth, fullScreen))
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-02-18 10:54:37 -08:00
|
|
|
return FALSE;
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialise the input system */
|
|
|
|
inputInitialise();
|
|
|
|
/* Initialise the frame rate stuff */
|
|
|
|
InitFrameStuff();
|
|
|
|
|
2006-07-05 13:39:13 -07:00
|
|
|
SDL_initFramerate( &wzFPSmanager );
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
// Initialise the resource stuff
|
|
|
|
if (!resInitialise())
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* frameUpdate
|
|
|
|
*
|
|
|
|
* Call this each cycle to allow the framework to deal with
|
|
|
|
* windows messages, and do general house keeping.
|
|
|
|
*
|
|
|
|
* Returns FRAME_STATUS.
|
|
|
|
*/
|
|
|
|
FRAME_STATUS frameUpdate(void)
|
|
|
|
{
|
|
|
|
SDL_Event event;
|
|
|
|
FRAME_STATUS retVal;
|
2006-10-09 12:00:20 -07:00
|
|
|
BOOL wzQuit = FALSE;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
/* Tell the input system about the start of another frame */
|
|
|
|
inputNewFrame();
|
|
|
|
|
|
|
|
/* Deal with any windows messages */
|
|
|
|
while ( SDL_PollEvent( &event ) != 0)
|
|
|
|
{
|
|
|
|
if (event.type == SDL_QUIT)
|
2006-10-09 12:00:20 -07:00
|
|
|
wzQuit = TRUE;
|
|
|
|
else
|
|
|
|
processEvent(&event);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now figure out what to return */
|
|
|
|
retVal = FRAME_OK;
|
2006-10-09 12:00:20 -07:00
|
|
|
if (wzQuit)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
retVal = FRAME_QUIT;
|
|
|
|
}
|
|
|
|
else if ((focusState == FOCUS_SET) && (focusLast == FOCUS_OUT))
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "Returning SETFOCUS\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
focusState = FOCUS_IN;
|
|
|
|
retVal = FRAME_SETFOCUS;
|
|
|
|
}
|
|
|
|
else if ((focusState == FOCUS_KILL) && (focusLast == FOCUS_IN))
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "Returning KILLFOCUS\n");
|
2007-06-28 10:47:08 -07:00
|
|
|
focusState = FOCUS_OUT;
|
|
|
|
retVal = FRAME_KILLFOCUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((focusState == FOCUS_SET) || (focusState == FOCUS_KILL))
|
|
|
|
{
|
|
|
|
/* Got a SET or KILL when we were already in or out of
|
|
|
|
focus respectively */
|
|
|
|
focusState = focusLast;
|
|
|
|
}
|
|
|
|
else if (focusLast != focusState)
|
|
|
|
{
|
2006-12-01 14:22:29 -08:00
|
|
|
debug( LOG_NEVER, "focusLast changing from %d to %d\n", focusLast, focusState);
|
2007-06-28 10:47:08 -07:00
|
|
|
focusLast = focusState;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If things are running normally update the framerate */
|
2006-10-09 12:00:20 -07:00
|
|
|
if ((!wzQuit) && (focusState == FOCUS_IN))
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
/* Update the frame rate stuff */
|
|
|
|
MaintainFrameStuff();
|
2006-07-05 13:39:13 -07:00
|
|
|
SDL_framerateDelay( &wzFPSmanager );
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void frameShutDown(void)
|
|
|
|
{
|
|
|
|
screenShutDown();
|
|
|
|
|
|
|
|
/* Free the default cursor */
|
|
|
|
// DestroyCursor(hCursor);
|
|
|
|
|
2006-02-18 10:54:37 -08:00
|
|
|
/* Free all cursors */
|
|
|
|
freeCursors();
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
/* Destroy the Application window */
|
|
|
|
SDL_Quit();
|
|
|
|
|
|
|
|
/* shutdown the trig stuff */
|
|
|
|
trigShutDown();
|
|
|
|
|
|
|
|
// Shutdown the resource stuff
|
|
|
|
resShutDown();
|
|
|
|
|
|
|
|
// shutdown the block memory heap
|
|
|
|
blkShutDown();
|
|
|
|
|
|
|
|
/* Shutdown the memory system */
|
|
|
|
memShutDown();
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
2006-02-18 10:54:37 -08:00
|
|
|
Load the file with name pointed to by pFileName into a memory buffer.
|
|
|
|
If AllocateMem is true then the memory is allocated ... else it is
|
|
|
|
already in allocated in ppFileData, and the max size is in pFileSize
|
2007-06-28 10:47:08 -07:00
|
|
|
... this is adjusted to the actual loaded file size.
|
2006-02-18 10:54:37 -08:00
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
If hard_fail is true, we will assert and report on failures.
|
|
|
|
***************************************************************************/
|
2006-11-02 11:33:46 -08:00
|
|
|
static BOOL loadFile2(const char *pFileName, char **ppFileData, UDWORD *pFileSize,
|
2007-06-28 10:47:08 -07:00
|
|
|
BOOL AllocateMem, BOOL hard_fail)
|
|
|
|
{
|
|
|
|
PHYSFS_file *pfile;
|
|
|
|
PHYSFS_sint64 filesize;
|
|
|
|
PHYSFS_sint64 length_read;
|
|
|
|
|
|
|
|
pfile = PHYSFS_openRead(pFileName);
|
|
|
|
if (!pfile) {
|
2006-12-02 03:09:36 -08:00
|
|
|
if (hard_fail) {
|
|
|
|
debug(LOG_ERROR, "loadFile2: file %s could not be opened: %s", pFileName, PHYSFS_getLastError());
|
2006-10-07 17:05:24 -07:00
|
|
|
assert(FALSE);
|
2006-12-02 03:09:36 -08:00
|
|
|
} else {
|
|
|
|
debug(LOG_WARNING, "loadFile2: optional file %s could not be opened: %s", pFileName, PHYSFS_getLastError());
|
|
|
|
}
|
2007-06-28 10:47:08 -07:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
filesize = PHYSFS_fileLength(pfile);
|
|
|
|
|
2005-11-30 13:09:38 -08:00
|
|
|
//debug(LOG_WZ, "loadFile2: %s opened, size %i", pFileName, filesize);
|
|
|
|
|
2007-06-28 10:47:08 -07:00
|
|
|
if (AllocateMem == TRUE) {
|
|
|
|
// Allocate a buffer to store the data and a terminating zero
|
2006-09-17 13:39:25 -07:00
|
|
|
*ppFileData = (char*)MALLOC(filesize + 1);
|
2007-06-28 10:47:08 -07:00
|
|
|
if (*ppFileData == NULL) {
|
|
|
|
debug(LOG_ERROR, "loadFile2: Out of memory loading %s", pFileName);
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (filesize > *pFileSize) {
|
|
|
|
debug(LOG_ERROR, "loadFile2: No room for file %s", pFileName);
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
assert(*ppFileData != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load the file data */
|
|
|
|
length_read = PHYSFS_read(pfile, *ppFileData, 1, filesize);
|
|
|
|
if (length_read != filesize) {
|
2006-07-07 07:08:48 -07:00
|
|
|
FREE( *ppFileData );
|
2007-06-28 10:47:08 -07:00
|
|
|
debug(LOG_ERROR, "loadFile2: Reading %s short: %s",
|
|
|
|
pFileName, PHYSFS_getLastError());
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!PHYSFS_close(pfile)) {
|
2006-07-07 07:08:48 -07:00
|
|
|
FREE( *ppFileData );
|
2007-06-28 10:47:08 -07:00
|
|
|
debug(LOG_ERROR, "loadFile2: Error closing %s: %s", pFileName,
|
|
|
|
PHYSFS_getLastError());
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the terminating zero
|
|
|
|
*((*ppFileData) + filesize) = 0;
|
|
|
|
|
|
|
|
// always set to correct size
|
|
|
|
*pFileSize = filesize;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Save the data in the buffer into the given file.
|
|
|
|
***************************************************************************/
|
|
|
|
BOOL saveFile(const char *pFileName, const char *pFileData, UDWORD fileSize)
|
|
|
|
{
|
|
|
|
PHYSFS_file *pfile;
|
|
|
|
PHYSFS_uint32 size = fileSize;
|
|
|
|
|
2006-10-07 07:13:47 -07:00
|
|
|
debug(LOG_WZ, "We are to write (%s) of size %d", pFileName, fileSize);
|
|
|
|
pfile = PHYSFS_openWrite(pFileName);
|
2007-06-28 10:47:08 -07:00
|
|
|
if (!pfile) {
|
2006-10-07 07:13:47 -07:00
|
|
|
const char *found = PHYSFS_getRealDir(pFileName);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-10-07 07:13:47 -07:00
|
|
|
debug(LOG_ERROR, "saveFile: %s could not be opened: %s", pFileName,
|
2007-06-28 10:47:08 -07:00
|
|
|
PHYSFS_getLastError());
|
|
|
|
if (found) {
|
2006-10-07 07:13:47 -07:00
|
|
|
debug(LOG_ERROR, "saveFile: %s found as %s", pFileName, found);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (PHYSFS_write(pfile, pFileData, 1, size) != size) {
|
2006-10-07 07:13:47 -07:00
|
|
|
debug(LOG_ERROR, "saveFile: %s could not write: %s", pFileName,
|
2007-06-28 10:47:08 -07:00
|
|
|
PHYSFS_getLastError());
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!PHYSFS_close(pfile)) {
|
2006-10-07 07:13:47 -07:00
|
|
|
debug(LOG_ERROR, "saveFile: Error closing %s: %s", pFileName,
|
2007-06-28 10:47:08 -07:00
|
|
|
PHYSFS_getLastError());
|
|
|
|
assert(FALSE);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-10-07 07:13:47 -07:00
|
|
|
if (PHYSFS_getRealDir(pFileName) == NULL) {
|
2007-06-28 10:47:08 -07:00
|
|
|
// weird
|
|
|
|
debug(LOG_ERROR, "saveFile: PHYSFS_getRealDir(%s) returns NULL?!",
|
2006-10-07 07:13:47 -07:00
|
|
|
pFileName);
|
2007-06-28 10:47:08 -07:00
|
|
|
} else {
|
2006-02-18 10:54:37 -08:00
|
|
|
debug(LOG_WZ, "Successfully wrote to %s%s%s with %d bytes",
|
2006-10-07 07:13:47 -07:00
|
|
|
PHYSFS_getRealDir(pFileName), PHYSFS_getDirSeparator(),
|
|
|
|
pFileName, size);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-08-12 09:52:37 -07:00
|
|
|
BOOL loadFile(const char *pFileName, char **ppFileData, UDWORD *pFileSize)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-10-07 07:13:47 -07:00
|
|
|
return loadFile2(pFileName, ppFileData, pFileSize, TRUE, TRUE);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// load a file from disk into a fixed memory buffer
|
2006-09-13 14:16:17 -07:00
|
|
|
BOOL loadFileToBuffer(const char *pFileName, char *pFileBuffer, UDWORD bufferSize, UDWORD *pSize)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
*pSize = bufferSize;
|
2006-10-07 07:13:47 -07:00
|
|
|
return loadFile2(pFileName, &pFileBuffer, pSize, FALSE, TRUE);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// as above but returns quietly if no file found
|
2006-09-13 14:16:17 -07:00
|
|
|
BOOL loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bufferSize, UDWORD *pSize)
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
|
|
|
*pSize = bufferSize;
|
2006-10-07 07:13:47 -07:00
|
|
|
return loadFile2(pFileName, &pFileBuffer, pSize, FALSE, FALSE);
|
2007-06-28 10:47:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* next four used in HashPJW */
|
|
|
|
#define BITS_IN_int 32
|
2006-11-03 17:11:26 -08:00
|
|
|
#define THREE_QUARTERS ((UDWORD) ((BITS_IN_int * 3) / 4))
|
|
|
|
#define ONE_EIGHTH ((UDWORD) (BITS_IN_int / 8))
|
|
|
|
#define HIGH_BITS ( ~((UDWORD)(~0) >> ONE_EIGHTH ))
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
//#define HIGH_BITS ((UDWORD)(0xf0000000))
|
|
|
|
//#define LOW_BITS ((UDWORD)(0x0fffffff))
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/*
|
|
|
|
* HashString
|
|
|
|
*
|
|
|
|
* Adaptation of Peter Weinberger's (PJW) generic hashing algorithm listed
|
|
|
|
* in Binstock+Rex, "Practical Algorithms" p 69.
|
|
|
|
*
|
|
|
|
* Accepts string and returns hashed integer.
|
|
|
|
*/
|
|
|
|
/***************************************************************************/
|
2006-11-03 17:11:26 -08:00
|
|
|
UDWORD HashString( const char *c )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-11-03 17:11:26 -08:00
|
|
|
UDWORD iHashValue, i;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
assert(c!=NULL);
|
|
|
|
assert(*c!=0x0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
for ( iHashValue=0; *c; ++c )
|
|
|
|
{
|
|
|
|
iHashValue = ( iHashValue << ONE_EIGHTH ) + *c;
|
|
|
|
|
|
|
|
if ( (i = iHashValue & HIGH_BITS) != 0 )
|
|
|
|
{
|
|
|
|
iHashValue = ( iHashValue ^ ( i >> THREE_QUARTERS ) ) &
|
|
|
|
~HIGH_BITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// printf("%%%%%%%% String:%s Hash:%0x\n",String,iHashValue);
|
|
|
|
return iHashValue;
|
|
|
|
}
|
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
UDWORD HashStringIgnoreCase( const char *c )
|
2007-06-28 10:47:08 -07:00
|
|
|
{
|
2006-11-03 17:11:26 -08:00
|
|
|
UDWORD iHashValue, i;
|
2007-06-28 10:47:08 -07:00
|
|
|
|
2006-11-03 17:11:26 -08:00
|
|
|
assert(c!=NULL);
|
|
|
|
assert(*c!=0x0);
|
2007-06-28 10:47:08 -07:00
|
|
|
|
|
|
|
for ( iHashValue=0; *c; ++c )
|
|
|
|
{
|
|
|
|
iHashValue = ( iHashValue << ONE_EIGHTH ) + ((*c)&(0xdf));
|
|
|
|
|
|
|
|
if ( (i = iHashValue & HIGH_BITS) != 0 )
|
|
|
|
{
|
|
|
|
iHashValue = ( iHashValue ^ ( i >> THREE_QUARTERS ) ) &
|
|
|
|
~HIGH_BITS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// printf("%%%%%%%% (Ignorcase) String:%s Hash:%0x\n",String,iHashValue);
|
|
|
|
return iHashValue;
|
|
|
|
}
|