mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-09-29 14:12:54 -04:00
Initial commit of the sharedFoundation library
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ByteOrder.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef BYTE_ORDER_H
|
||||
#define BYTE_ORDER_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstPlatform.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedFoundation.cpp
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/ConfigSharedFoundation.h"
|
||||
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
const int c_defaultFatalCallStackDepth = 32;
|
||||
const int c_defaultWarningCallStackDepth = 8;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace ConfigSharedFoundationNamespace
|
||||
{
|
||||
real ms_frameRateLimit;
|
||||
real ms_minFrameRate;
|
||||
bool ms_noExceptionHandling;
|
||||
|
||||
bool ms_fpuExceptionPrecision;
|
||||
bool ms_fpuExceptionUnderflow;
|
||||
bool ms_fpuExceptionOverflow;
|
||||
bool ms_fpuExceptionZeroDivide;
|
||||
bool ms_fpuExceptionDenormal;
|
||||
bool ms_fpuExceptionInvalid;
|
||||
|
||||
bool ms_demoMode;
|
||||
|
||||
bool ms_useRemoteDebug;
|
||||
int ms_defaultRemoteDebugPort;
|
||||
|
||||
bool ms_profilerExpandAllBranches = true;
|
||||
|
||||
bool ms_memoryManagerReportAllocations;
|
||||
bool ms_memoryManagerReportOnOutOfMemory;
|
||||
|
||||
bool ms_useMemoryBlockManager;
|
||||
bool ms_memoryBlockManagerDebugDumpOnRemove;
|
||||
|
||||
int ms_fatalCallStackDepth;
|
||||
int ms_warningCallStackDepth;
|
||||
bool ms_lookUpCallStackNames;
|
||||
|
||||
bool ms_alwaysCanSeeWorldCell;
|
||||
|
||||
bool ms_verboseWarnings;
|
||||
|
||||
float ms_debugReportLongFrameTime;
|
||||
}
|
||||
|
||||
using namespace ConfigSharedFoundationNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedFoundation", #a, b))
|
||||
#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedFoundation", #a, b))
|
||||
#define KEY_FLOAT(a,b) (ms_ ## a = ConfigFile::getKeyFloat("SharedFoundation", #a, b))
|
||||
// #define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedFoundation", #a, b))
|
||||
|
||||
// ======================================================================
|
||||
// Determine the Platform-specific configuration information
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// This routine inspects the ConfigFile class to set some variables for rapid access
|
||||
// by the rest of the engine.
|
||||
|
||||
void ConfigSharedFoundation::install (const Defaults &defaults)
|
||||
{
|
||||
KEY_BOOL(noExceptionHandling, false);
|
||||
|
||||
KEY_BOOL(fpuExceptionPrecision, false);
|
||||
KEY_BOOL(fpuExceptionUnderflow, false);
|
||||
KEY_BOOL(fpuExceptionOverflow, false);
|
||||
KEY_BOOL(fpuExceptionZeroDivide, false);
|
||||
KEY_BOOL(fpuExceptionDenormal, false);
|
||||
KEY_BOOL(fpuExceptionInvalid, false);
|
||||
|
||||
KEY_BOOL(demoMode, false);
|
||||
|
||||
KEY_FLOAT(frameRateLimit, defaults.frameRateLimit);
|
||||
KEY_FLOAT(minFrameRate, 0.0f);
|
||||
|
||||
KEY_BOOL(useRemoteDebug, false);
|
||||
KEY_INT(defaultRemoteDebugPort, 4445);
|
||||
|
||||
KEY_BOOL(profilerExpandAllBranches, true);
|
||||
KEY_BOOL(memoryManagerReportAllocations, true);
|
||||
KEY_BOOL(memoryManagerReportOnOutOfMemory, true);
|
||||
|
||||
KEY_BOOL(useMemoryBlockManager, true);
|
||||
KEY_BOOL(memoryBlockManagerDebugDumpOnRemove, false);
|
||||
|
||||
KEY_INT(fatalCallStackDepth, c_defaultFatalCallStackDepth);
|
||||
KEY_INT(warningCallStackDepth, c_defaultWarningCallStackDepth);
|
||||
KEY_BOOL(lookUpCallStackNames, true);
|
||||
|
||||
KEY_BOOL(alwaysCanSeeWorldCell, false);
|
||||
|
||||
KEY_BOOL(verboseWarnings, false);
|
||||
|
||||
KEY_FLOAT(debugReportLongFrameTime, 0.25f);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
/**
|
||||
* Return the frame rate limit value for the game.
|
||||
*
|
||||
* @return The initial frame rate limiter value
|
||||
*/
|
||||
|
||||
real ConfigSharedFoundation::getFrameRateLimit(void)
|
||||
{
|
||||
return ms_frameRateLimit;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return the minimum frame rate limit value for the game. Frame that take longer
|
||||
* will be set to the minimum and a message will be logged.
|
||||
*
|
||||
* @return The minimum frame rate value
|
||||
*/
|
||||
|
||||
real ConfigSharedFoundation::getMinFrameRate(void)
|
||||
{
|
||||
return ms_minFrameRate;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return whether to run with exception handling enabled.
|
||||
*
|
||||
* @return True to run without exception handling
|
||||
*/
|
||||
|
||||
bool ConfigSharedFoundation::getNoExceptionHandling(void)
|
||||
{
|
||||
return ms_noExceptionHandling;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionPrecision(void)
|
||||
{
|
||||
return ms_fpuExceptionPrecision;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionUnderflow(void)
|
||||
{
|
||||
return ms_fpuExceptionUnderflow;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionOverflow(void)
|
||||
{
|
||||
return ms_fpuExceptionOverflow;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionZeroDivide(void)
|
||||
{
|
||||
return ms_fpuExceptionZeroDivide;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionDenormal(void)
|
||||
{
|
||||
return ms_fpuExceptionDenormal;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getFpuExceptionInvalid(void)
|
||||
{
|
||||
return ms_fpuExceptionInvalid;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedFoundation::getFatalCallStackDepth()
|
||||
{
|
||||
return ms_fatalCallStackDepth;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedFoundation::getWarningCallStackDepth()
|
||||
{
|
||||
return ms_warningCallStackDepth;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getProfilerExpandAllBranches()
|
||||
{
|
||||
return ms_profilerExpandAllBranches;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getUseRemoteDebug()
|
||||
{
|
||||
return ms_useRemoteDebug;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedFoundation::getDefaultRemoteDebugPort()
|
||||
{
|
||||
return ms_defaultRemoteDebugPort;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getDemoMode()
|
||||
{
|
||||
return ms_demoMode;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getAlwaysCanSeeWorldCell()
|
||||
{
|
||||
return ms_alwaysCanSeeWorldCell;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getLookUpCallStackNames()
|
||||
{
|
||||
return ms_lookUpCallStackNames;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getMemoryManagerReportAllocations()
|
||||
{
|
||||
return ms_memoryManagerReportAllocations;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getMemoryManagerReportOnOutOfMemory()
|
||||
{
|
||||
return ms_memoryManagerReportOnOutOfMemory;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getUseMemoryBlockManager()
|
||||
{
|
||||
return ms_useMemoryBlockManager;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getMemoryBlockManagerDebugDumpOnRemove ()
|
||||
{
|
||||
return ms_memoryBlockManagerDebugDumpOnRemove;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedFoundation::getVerboseWarnings()
|
||||
{
|
||||
return ms_verboseWarnings;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
float ConfigSharedFoundation::getDebugReportLongFrameTime()
|
||||
{
|
||||
return ms_debugReportLongFrameTime;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,64 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedFoundation.h
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ConfigSharedFoundation_H
|
||||
#define INCLUDED_ConfigSharedFoundation_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class ConfigSharedFoundation
|
||||
{
|
||||
public:
|
||||
|
||||
struct Defaults
|
||||
{
|
||||
real frameRateLimit;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static void install (const Defaults &defaults);
|
||||
|
||||
static real getFrameRateLimit();
|
||||
static real getMinFrameRate();
|
||||
static bool getNoExceptionHandling();
|
||||
|
||||
static bool getFpuExceptionPrecision();
|
||||
static bool getFpuExceptionUnderflow();
|
||||
static bool getFpuExceptionOverflow();
|
||||
static bool getFpuExceptionZeroDivide();
|
||||
static bool getFpuExceptionDenormal();
|
||||
static bool getFpuExceptionInvalid();
|
||||
|
||||
static bool getDemoMode();
|
||||
|
||||
static bool getUseRemoteDebug();
|
||||
static int getDefaultRemoteDebugPort();
|
||||
|
||||
static bool getProfilerExpandAllBranches();
|
||||
|
||||
static bool getMemoryManagerReportAllocations();
|
||||
static bool getMemoryManagerReportOnOutOfMemory();
|
||||
|
||||
static bool getUseMemoryBlockManager();
|
||||
static bool getMemoryBlockManagerDebugDumpOnRemove();
|
||||
|
||||
static int getFatalCallStackDepth();
|
||||
static int getWarningCallStackDepth();
|
||||
static bool getLookUpCallStackNames();
|
||||
|
||||
static bool getAlwaysCanSeeWorldCell();
|
||||
|
||||
static bool getVerboseWarnings();
|
||||
|
||||
static float getDebugReportLongFrameTime();
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstPlatform.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef FIRST_PLATFORM_H
|
||||
#define FIRST_PLATFORM_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#define DLLEXPORT
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// C4514 unreferenced inline function has been removed
|
||||
// C4710 inline function not expanded
|
||||
// C4291 no matching operator delete found; memory will not be freed if initialization throws an exception
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "sharedFoundation/PlatformGlue.h"
|
||||
#include "sharedMemoryManager/MemoryManager.h"
|
||||
|
||||
|
||||
// ======================================================================
|
||||
|
||||
template <class T>
|
||||
inline int ComGetReferenceCount(T *t)
|
||||
{
|
||||
t->AddRef();
|
||||
return t->Release();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#define FATAL_HR(a,b) FATAL(FAILED(b), (a, HRESULT_CODE(b)))
|
||||
#define DEBUG_FATAL_HR(a,b) DEBUG_FATAL(FAILED(b), (a, HRESULT_CODE(b)))
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,266 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FloatingPointUnit.cpp
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1999 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/FloatingPointUnit.h"
|
||||
|
||||
#include "sharedFoundation/ConfigSharedFoundation.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
int FloatingPointUnit::updateNumber;
|
||||
WORD FloatingPointUnit::status;
|
||||
FloatingPointUnit::Precision FloatingPointUnit::precision;
|
||||
FloatingPointUnit::Rounding FloatingPointUnit::rounding;
|
||||
bool FloatingPointUnit::exceptionEnabled[E_max];
|
||||
|
||||
// ======================================================================
|
||||
|
||||
const WORD PRECISION_MASK = BINARY4(0000,0011,0000,0000);
|
||||
const WORD PRECISION_24 = BINARY4(0000,0000,0000,0000);
|
||||
const WORD PRECISION_53 = BINARY4(0000,0010,0000,0000);
|
||||
const WORD PRECISION_64 = BINARY4(0000,0011,0000,0000);
|
||||
|
||||
const WORD ROUND_MASK = BINARY4(0000,1100,0000,0000);
|
||||
const WORD ROUND_NEAREST = BINARY4(0000,0000,0000,0000);
|
||||
const WORD ROUND_CHOP = BINARY4(0000,1100,0000,0000);
|
||||
const WORD ROUND_DOWN = BINARY4(0000,0100,0000,0000);
|
||||
const WORD ROUND_UP = BINARY4(0000,1000,0000,0000);
|
||||
|
||||
const WORD EXCEPTION_PRECISION = BINARY4(0000,0000,0010,0000);
|
||||
const WORD EXCEPTION_UNDERFLOW = BINARY4(0000,0000,0001,0000);
|
||||
const WORD EXCEPTION_OVERFLOW = BINARY4(0000,0000,0000,1000);
|
||||
const WORD EXCEPTION_ZERO_DIVIDE = BINARY4(0000,0000,0000,0100);
|
||||
const WORD EXCEPTION_DENORMAL = BINARY4(0000,0000,0000,0010);
|
||||
const WORD EXCEPTION_INVALID = BINARY4(0000,0000,0000,0001);
|
||||
const WORD EXCEPTION_ALL = BINARY4(0000,0000,0011,1111);
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void FloatingPointUnit::install(void)
|
||||
{
|
||||
precision = P_24;
|
||||
rounding = R_roundToNearestOrEven;
|
||||
memset(exceptionEnabled, 0, sizeof(exceptionEnabled));
|
||||
|
||||
// preserve all other bits
|
||||
status = getControlWord();
|
||||
status &= ~(PRECISION_MASK | ROUND_MASK | EXCEPTION_ALL);
|
||||
|
||||
// set to single precision, rounding, and all exceptions masked
|
||||
status |= PRECISION_24 | ROUND_NEAREST | EXCEPTION_ALL;
|
||||
|
||||
// check the config platform flags to see if we should enable some exceptions
|
||||
if (ConfigSharedFoundation::getFpuExceptionPrecision())
|
||||
{
|
||||
exceptionEnabled[E_precision] = true;
|
||||
status &= ~EXCEPTION_PRECISION;
|
||||
}
|
||||
|
||||
if (ConfigSharedFoundation::getFpuExceptionUnderflow())
|
||||
{
|
||||
exceptionEnabled[E_underflow] = true;
|
||||
status &= ~EXCEPTION_UNDERFLOW;
|
||||
}
|
||||
|
||||
if (ConfigSharedFoundation::getFpuExceptionOverflow())
|
||||
{
|
||||
exceptionEnabled[E_overflow] = true;
|
||||
status &= ~EXCEPTION_OVERFLOW;
|
||||
}
|
||||
|
||||
if (ConfigSharedFoundation::getFpuExceptionZeroDivide())
|
||||
{
|
||||
exceptionEnabled[E_zeroDivide] = true;
|
||||
status &= ~EXCEPTION_ZERO_DIVIDE;
|
||||
}
|
||||
|
||||
if (ConfigSharedFoundation::getFpuExceptionDenormal())
|
||||
{
|
||||
exceptionEnabled[E_denormal] = true;
|
||||
status &= ~EXCEPTION_DENORMAL;
|
||||
}
|
||||
|
||||
if (ConfigSharedFoundation::getFpuExceptionInvalid())
|
||||
{
|
||||
exceptionEnabled[E_invalid] = true;
|
||||
status &= ~EXCEPTION_INVALID;
|
||||
}
|
||||
|
||||
setControlWord(status);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FloatingPointUnit::update(void)
|
||||
{
|
||||
WORD currentStatus = getControlWord();
|
||||
|
||||
if (currentStatus != status)
|
||||
{
|
||||
DEBUG_REPORT_LOG_PRINT(true, ("FPU: update=%d, in mode=%04x, should be in mode=%04x", updateNumber, static_cast<int>(currentStatus), static_cast<int>(status)));
|
||||
setControlWord(status);
|
||||
}
|
||||
|
||||
++updateNumber;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
WORD FloatingPointUnit::getControlWord(void)
|
||||
{
|
||||
//TODO wtf is this asm statement?
|
||||
#if 0
|
||||
WORD controlWord = 0;
|
||||
__asm fnstcw controlWord;
|
||||
return controlWord;
|
||||
#else
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FloatingPointUnit::setControlWord(WORD controlWord)
|
||||
{
|
||||
//TODO see above?
|
||||
|
||||
UNREF(controlWord);
|
||||
#if 0
|
||||
__asm fldcw controlWord;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FloatingPointUnit::setPrecision(Precision newPrecision)
|
||||
{
|
||||
WORD bits = 0;
|
||||
|
||||
switch (precision)
|
||||
{
|
||||
case P_24:
|
||||
bits = PRECISION_24;
|
||||
break;
|
||||
|
||||
case P_53:
|
||||
bits = PRECISION_53;
|
||||
break;
|
||||
|
||||
case P_64:
|
||||
bits = PRECISION_64;
|
||||
break;
|
||||
|
||||
case P_max:
|
||||
default:
|
||||
DEBUG_FATAL(true, ("bad case"));
|
||||
}
|
||||
|
||||
// record the current state
|
||||
precision = newPrecision;
|
||||
|
||||
// set the proper bit pattern
|
||||
status &= ~PRECISION_MASK;
|
||||
status |= bits;
|
||||
|
||||
// slam it into the FPU
|
||||
setControlWord(status);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FloatingPointUnit::setRounding(Rounding newRounding)
|
||||
{
|
||||
WORD bits = 0;
|
||||
|
||||
switch (newRounding)
|
||||
{
|
||||
case R_roundToNearestOrEven:
|
||||
bits = ROUND_NEAREST;
|
||||
break;
|
||||
|
||||
case R_chop:
|
||||
bits = ROUND_CHOP;
|
||||
break;
|
||||
|
||||
case R_roundDown:
|
||||
bits = ROUND_DOWN;
|
||||
break;
|
||||
|
||||
case R_roundUp:
|
||||
bits = ROUND_UP;
|
||||
break;
|
||||
|
||||
case R_max:
|
||||
default:
|
||||
DEBUG_FATAL(true, ("bad case"));
|
||||
}
|
||||
|
||||
// record the current state
|
||||
rounding = newRounding;
|
||||
|
||||
// set the proper bit pattern
|
||||
status &= ~ROUND_MASK;
|
||||
status |= bits;
|
||||
|
||||
// slam it into the FPU
|
||||
setControlWord(status);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FloatingPointUnit::setExceptionEnabled(Exception exception, bool enabled)
|
||||
{
|
||||
WORD bits = 0;
|
||||
|
||||
switch (exception)
|
||||
{
|
||||
case E_precision:
|
||||
bits = EXCEPTION_PRECISION;
|
||||
break;
|
||||
|
||||
case E_underflow:
|
||||
bits = EXCEPTION_UNDERFLOW;
|
||||
break;
|
||||
|
||||
case E_overflow:
|
||||
bits = EXCEPTION_OVERFLOW;
|
||||
break;
|
||||
|
||||
case E_zeroDivide:
|
||||
bits = EXCEPTION_ZERO_DIVIDE;
|
||||
break;
|
||||
|
||||
case E_denormal:
|
||||
bits = EXCEPTION_DENORMAL;
|
||||
break;
|
||||
|
||||
case E_invalid:
|
||||
bits = EXCEPTION_INVALID;
|
||||
break;
|
||||
|
||||
case E_max:
|
||||
default:
|
||||
DEBUG_FATAL(true, ("bad case"));
|
||||
}
|
||||
|
||||
// record the current state
|
||||
exceptionEnabled[exception] = enabled;
|
||||
|
||||
// twiddle the bit appropriately. these bits masks, so set the bit to disable the exception, clear the bit to enable it.
|
||||
if (enabled)
|
||||
status &= ~bits;
|
||||
else
|
||||
status |= bits;
|
||||
|
||||
// slam it into the FPU
|
||||
setControlWord(status);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,102 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FloatingPointUnit.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1999 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef FLOATING_POINT_UNIT_H
|
||||
#define FLOATING_POINT_UNIT_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class FloatingPointUnit
|
||||
{
|
||||
public:
|
||||
|
||||
enum Precision
|
||||
{
|
||||
P_24,
|
||||
P_53,
|
||||
P_64,
|
||||
|
||||
P_max
|
||||
};
|
||||
|
||||
enum Rounding
|
||||
{
|
||||
R_roundToNearestOrEven,
|
||||
R_chop,
|
||||
R_roundDown,
|
||||
R_roundUp,
|
||||
|
||||
R_max
|
||||
};
|
||||
|
||||
enum Exception
|
||||
{
|
||||
E_precision,
|
||||
E_underflow,
|
||||
E_overflow,
|
||||
E_zeroDivide,
|
||||
E_denormal,
|
||||
E_invalid,
|
||||
|
||||
E_max
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static int updateNumber;
|
||||
static WORD status;
|
||||
static Precision precision;
|
||||
static Rounding rounding;
|
||||
static bool exceptionEnabled[E_max];
|
||||
|
||||
public:
|
||||
|
||||
static WORD getControlWord(void);
|
||||
static void setControlWord(WORD controlWord);
|
||||
|
||||
public:
|
||||
|
||||
static void install(void);
|
||||
|
||||
static void update(void);
|
||||
|
||||
static void setPrecision(Precision newPrecision);
|
||||
static void setRounding(Rounding newRounding);
|
||||
static void setExceptionEnabled(Exception exception, bool enabled);
|
||||
|
||||
static Precision getPrecision(void);
|
||||
static Rounding getRounding(void);
|
||||
static bool getExceptionEnabled(Exception exception);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline FloatingPointUnit::Precision FloatingPointUnit::getPrecision(void)
|
||||
{
|
||||
return precision;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline FloatingPointUnit::Rounding FloatingPointUnit::getRounding(void)
|
||||
{
|
||||
return rounding;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool FloatingPointUnit::getExceptionEnabled(Exception exception)
|
||||
{
|
||||
DEBUG_FATAL(static_cast<int>(exception) < 0 || static_cast<int>(exception) >= static_cast<int>(E_max), ("exception out of range")); //lint !e568 // non-negative quantity is never less than 0
|
||||
return exceptionEnabled[exception];
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,468 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Os.cpp
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
|
||||
#include "sharedFoundation/Clock.h"
|
||||
#include "sharedFoundation/ConfigSharedFoundation.h"
|
||||
#include "sharedDebug/DebugMonitor.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/FloatingPointUnit.h"
|
||||
#include "sharedIoWin/IoWinManager.h"
|
||||
|
||||
#include <stack>
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
bool Os::installed;
|
||||
bool Os::runInBackground;
|
||||
int Os::numberOfUpdates;
|
||||
int Os::menuValue;
|
||||
bool Os::paused;
|
||||
bool Os::wasPaused;
|
||||
bool Os::gameOver;
|
||||
bool Os::shouldReturnFromAbort;
|
||||
char Os::programName[PROGRAM_NAME_SIZE];
|
||||
char *Os::shortProgramName;
|
||||
pthread_t Os::mainThreadId;
|
||||
bool Os::threadDied;
|
||||
|
||||
bool Os::isMp;
|
||||
int Os::processorCount;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
namespace OsNamespace
|
||||
{
|
||||
class UncatchableException
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Install the Os subsystem for non-games.
|
||||
*
|
||||
* This routine is supported for all platforms, although different platforms may
|
||||
* require different arguments to this routine.
|
||||
*
|
||||
* This routine will add Os::remove to the ExitChain.
|
||||
*
|
||||
* @see Os::remove()
|
||||
*/
|
||||
|
||||
void Os::install(void)
|
||||
{
|
||||
installCommon();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* This routine will remove the Os subsystem.
|
||||
*
|
||||
* This routine should not be called directly. It will be called from the ExitChain.
|
||||
*
|
||||
* @see Os::install()
|
||||
*/
|
||||
|
||||
void Os::remove(void)
|
||||
{
|
||||
DEBUG_FATAL(!installed, ("not installed"));
|
||||
installed = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Os::installCommon(void)
|
||||
{
|
||||
DEBUG_FATAL(installed, ("already installed"));
|
||||
|
||||
ExitChain::add(Os::remove, "Os::remove", 0, true);
|
||||
|
||||
#if 0 //TODO For now we won't screw with the priority of the process
|
||||
HANDLE threadHandle = GetCurrentThread();
|
||||
DEBUG_FATAL(!SetThreadPriority(threadHandle, THREAD_PRIORITY_ABOVE_NORMAL), ("Failed to set game thread priority"));
|
||||
#endif
|
||||
|
||||
numberOfUpdates = 0;
|
||||
mainThreadId = pthread_self();
|
||||
|
||||
// get the name of the executable
|
||||
//Can't find UNIX call for this: DWORD result = GetModuleFileName(NULL, programName, sizeof(programName));
|
||||
strcpy(programName, "TempName");
|
||||
DWORD result = 1;
|
||||
|
||||
|
||||
FATAL(result == 0, ("GetModuleFileName failed"));
|
||||
|
||||
// get the file name without the path
|
||||
shortProgramName = strrchr(programName, '\\');
|
||||
if (shortProgramName)
|
||||
++shortProgramName;
|
||||
else
|
||||
shortProgramName = programName;
|
||||
|
||||
// determine the number of processors by parsing /proc/cpuinfo
|
||||
processorCount = 1;
|
||||
FILE * f = fopen("/proc/cpuinfo", "r");
|
||||
if (f)
|
||||
{
|
||||
char buffer[512];
|
||||
while (!feof(f))
|
||||
{
|
||||
fgets(buffer, 512, f);
|
||||
if (strncmp(buffer, "processor\t: ", 12)==0)
|
||||
{
|
||||
processorCount = atoi(buffer+12)+1;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
isMp = processorCount > 1;
|
||||
|
||||
// switch into single-precision floating point mode
|
||||
FloatingPointUnit::install();
|
||||
|
||||
installed = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Os::isMainThread(void)
|
||||
{
|
||||
// if the Os class hasn't been installed, then assume we are the main thread.
|
||||
// otherwise, check to see if our thread id is the main thread id
|
||||
return !installed || (pthread_self() == mainThreadId);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Terminate the application because of an error condition.
|
||||
*
|
||||
* This routine is supported for all platforms.
|
||||
*
|
||||
* This routine should not be called directly. The engine and game should use the
|
||||
* FATAL macro to terminate the application because of an error.
|
||||
*
|
||||
* Calling Os::returnFromAbort() will cause the routine to do nothing but return
|
||||
* immediately.
|
||||
*
|
||||
* @see Os::returnFromAbort(), FATAL()
|
||||
*/
|
||||
#include <signal.h>
|
||||
void Os::abort(void)
|
||||
{
|
||||
if (!isMainThread())
|
||||
{
|
||||
threadDied = true;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
if (!shouldReturnFromAbort)
|
||||
{
|
||||
// let the C runtime deal with the abnormal termination
|
||||
int * dummy = NULL;
|
||||
int forceCrash = *dummy;
|
||||
UNREF(forceCrash);
|
||||
for (;;)
|
||||
{
|
||||
// One of these should work:
|
||||
pthread_kill(pthread_self(), SIGSEGV);
|
||||
::kill(0,SIGSEGV);
|
||||
::abort();
|
||||
OsNamespace::UncatchableException ex;
|
||||
throw ex;
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
/**
|
||||
* Create the specified directory and all of it's parents.
|
||||
* @param directory the path to a directory
|
||||
* @return always true currently
|
||||
*/
|
||||
|
||||
bool Os::createDirectories (const char *directory)
|
||||
{
|
||||
//-- construct list of subdirectories all the way down to root
|
||||
std::stack<std::string> directoryStack;
|
||||
|
||||
std::string currentDirectory = directory;
|
||||
|
||||
static const char path_seps [] = { '\\', '/', 0 };
|
||||
|
||||
// build the stack
|
||||
while (!currentDirectory.empty())
|
||||
{
|
||||
// remove trailing backslash
|
||||
if (currentDirectory[currentDirectory.size()-1] == '\\' || currentDirectory[currentDirectory.size()-1] == '/')
|
||||
IGNORE_RETURN(currentDirectory.erase(currentDirectory.size()-1));
|
||||
|
||||
if (currentDirectory[currentDirectory.size()-1] == ':')
|
||||
{
|
||||
// we've hit something like c:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!currentDirectory.empty())
|
||||
directoryStack.push(currentDirectory);
|
||||
|
||||
// now strip off current directory
|
||||
size_t previousDirIndex = currentDirectory.find_last_of (path_seps);
|
||||
if (previousDirIndex == currentDirectory.npos)
|
||||
break;
|
||||
else
|
||||
IGNORE_RETURN(currentDirectory.erase(previousDirIndex));
|
||||
}
|
||||
|
||||
//-- build all directories specified by the initial directory
|
||||
while (!directoryStack.empty())
|
||||
{
|
||||
// get the directory
|
||||
currentDirectory = directoryStack.top();
|
||||
directoryStack.pop();
|
||||
|
||||
// try to create it (don't pass any security attributes)
|
||||
IGNORE_RETURN (mkdir (currentDirectory.c_str(), 0));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Write out a file.
|
||||
*
|
||||
* The file name and where the file is written is system-dependent.
|
||||
*
|
||||
* @param fileName Name of the file to write
|
||||
* @param data Data buffer to write to the file
|
||||
*/
|
||||
|
||||
bool Os::writeFile(const char *fileName, const void *data, int length) // Length of the data bufferto write
|
||||
{
|
||||
BOOL result;
|
||||
HANDLE handle;
|
||||
DWORD written;
|
||||
|
||||
// open the file for writing
|
||||
handle = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
// check if it was opened
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// attempt to write the data
|
||||
result = WriteFile(handle, data, static_cast<DWORD>(length), &written, NULL);
|
||||
|
||||
// make sure the data was written okay
|
||||
if (!result || written != static_cast<DWORD>(length))
|
||||
{
|
||||
static_cast<void>(CloseHandle(handle));
|
||||
return false;
|
||||
}
|
||||
|
||||
// close the file
|
||||
result = CloseHandle(handle);
|
||||
|
||||
// make sure the close was sucessful
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Update the Os subsystem.
|
||||
*
|
||||
* This routine is supported for all platforms.
|
||||
*
|
||||
* For the Win* platforms, this routine will process the windows message pump.
|
||||
*/
|
||||
|
||||
bool Os::update(void)
|
||||
{
|
||||
static int ppid = getppid();
|
||||
|
||||
FloatingPointUnit::update();
|
||||
|
||||
++numberOfUpdates;
|
||||
|
||||
#if 0
|
||||
#ifdef _DEBUG
|
||||
|
||||
if (DEBUG_FLAG_PLATFORM(validateHeap))
|
||||
{
|
||||
PROFILER_START("validate heap");
|
||||
MemoryManager::validate();
|
||||
PROFILER_STOP("validate heap");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Clock::update();
|
||||
|
||||
wasPaused = false;
|
||||
|
||||
// if our parent's pid has changed, we tell our caller it should exit
|
||||
if (getppid() != ppid)
|
||||
{
|
||||
WARNING(true, ("Parent process exited!"));
|
||||
// reset the parent process id, so we don't keep spamming warnings for processes that don't exit because of this
|
||||
ppid = getppid();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Formats a message error using GetLastError() and FormatMessge().
|
||||
*
|
||||
* The buffer returned from this function is dynamically allocated to prevent
|
||||
* issues with this routine being called from multiple threads. The caller
|
||||
* must delete the buffer when it is done.
|
||||
*
|
||||
* @return A dynamically allocated buffer containing the error message
|
||||
*/
|
||||
|
||||
char *Os::getLastError(void)
|
||||
{
|
||||
return DuplicateString(strerror(errno));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Os::getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize)
|
||||
{
|
||||
// realpath sucks and could cause a buffer overrun. however, it's better than writing it ourselves for now.
|
||||
char *result = realpath(relativePath, absolutePath);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
FATAL(istrlen(absolutePath)+1 > absolutePathBufferSize, ("buffer overrun"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get the actual system time, in seconds since the epoch.
|
||||
*
|
||||
* Do not use this for most game systems, since it does not take into account
|
||||
* clock sku, game loop times, etc.
|
||||
*/
|
||||
time_t Os::getRealSystemTime(void)
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Convert a time in seconds since the epoch to GMT.
|
||||
*
|
||||
*/
|
||||
|
||||
void Os::convertTimeToGMT(const time_t &time, tm &zulu)
|
||||
{
|
||||
zulu=*gmtime(&time); // gmtime uses a single static tm structure. Yuck!
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Convert a tm structure to the time in seconds since the epoch.
|
||||
*
|
||||
*/
|
||||
|
||||
time_t Os::convertGMTToTime(const tm &zulu)
|
||||
{
|
||||
return mktime(const_cast<tm*>(&zulu));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get a unique identifier for this thread.
|
||||
*
|
||||
* @return A unique identifier for this thread.
|
||||
*/
|
||||
|
||||
Os::ThreadId Os::getThreadId()
|
||||
{
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Assign the given thread a reasonable name (only works for MSDev 6.0 debugger)
|
||||
* Since this is Linux-specific, make sure this fuction does nothing
|
||||
*
|
||||
*/
|
||||
|
||||
void Os::setThreadName(DWORD threadID, const char* threadName)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Cause the current thread to sleep for a period of time. If the period is
|
||||
* zero, the current thread yields it's timeslice.
|
||||
*/
|
||||
|
||||
void Os::sleep(int ms)
|
||||
{
|
||||
if (ms == 0)
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Copy text to the system clipboard.
|
||||
*
|
||||
* This routine can be used if the application wants to make some data easily available for pasting (like crash call stacks).
|
||||
*/
|
||||
|
||||
bool Os::copyTextToClipboard(const char *text)
|
||||
{
|
||||
UNREF(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
Os::OsPID_t Os::getProcessId()
|
||||
{
|
||||
return getpid();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void Os::setProgramName(const char * name)
|
||||
{
|
||||
strncpy(programName, name, Os::PROGRAM_NAME_SIZE);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool Os::isFocused()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -0,0 +1,264 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Os.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef OS_H
|
||||
#define OS_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct DebugMenuEntry;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class Os
|
||||
{
|
||||
public:
|
||||
|
||||
typedef pthread_t ThreadId;
|
||||
typedef pid_t OsPID_t;
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_PATH_LENGTH = 512
|
||||
};
|
||||
|
||||
typedef void (*QueueCharacterHookFunction)(int keyboard, int character);
|
||||
typedef void (*SetSystemMouseCursorPositionHookFunction)(int x, int y);
|
||||
typedef void (*QueueKeyDownHookFunction)(int keyboard, int character);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Os(void);
|
||||
Os(const Os &);
|
||||
Os &operator =(const Os &);
|
||||
|
||||
enum
|
||||
{
|
||||
PROGRAM_NAME_SIZE = 512
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static void remove(void);
|
||||
|
||||
static void installCommon(void);
|
||||
|
||||
private:
|
||||
|
||||
static bool installed;
|
||||
static bool runInBackground;
|
||||
static int numberOfUpdates;
|
||||
static int menuValue;
|
||||
static DebugMenuEntry *debugMenuGame;
|
||||
static bool paused;
|
||||
static bool wasPaused;
|
||||
static bool gameOver;
|
||||
static bool shouldReturnFromAbort;
|
||||
static bool wantPopupDebugMenu;
|
||||
static char programName[PROGRAM_NAME_SIZE];
|
||||
static char *shortProgramName;
|
||||
static pthread_t mainThreadId;
|
||||
static bool threadDied;
|
||||
static bool isMp;
|
||||
static int processorCount;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static void install(void);
|
||||
|
||||
static bool isGameOver(void);
|
||||
static bool isMainThread(void);
|
||||
static bool wasApplicationPaused(void);
|
||||
|
||||
static bool update(void);
|
||||
|
||||
static void returnFromAbort(void);
|
||||
static void abort(void);
|
||||
|
||||
static void requestPopupDebugMenu();
|
||||
|
||||
static bool createDirectories (const char *dirname);
|
||||
|
||||
static bool writeFile(const char *fileName, const void *data, int length);
|
||||
|
||||
static int getNumberOfUpdates(void);
|
||||
|
||||
static char *getLastError(void);
|
||||
|
||||
static void setThreadName(DWORD threadID, const char* name);
|
||||
static ThreadId getThreadId();
|
||||
|
||||
static const char *getProgramName(void);
|
||||
static const char *getShortProgramName(void);
|
||||
static void setProgramName(const char * name);
|
||||
|
||||
static bool getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize);
|
||||
|
||||
static void sleep(int ms);
|
||||
|
||||
static time_t getRealSystemTime(void);
|
||||
static void convertTimeToGMT(const time_t &time, tm &zulu);
|
||||
static time_t convertGMTToTime(const tm &zulu);
|
||||
|
||||
static bool isMultiprocessor();
|
||||
static int getProcessorCount();
|
||||
|
||||
static bool copyTextToClipboard(const char *text);
|
||||
|
||||
static bool wasFocusLost();
|
||||
static void setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction);
|
||||
static void setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction);
|
||||
static OsPID_t getProcessId();
|
||||
static bool isFocused();
|
||||
|
||||
static void setQueueKeyDownHookFunction(QueueKeyDownHookFunction queueKeyDownHookFunction);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return the full name of the running executable.
|
||||
*
|
||||
* The program name will include the path as well.
|
||||
*
|
||||
* @return The full name of the running executable
|
||||
* @see Os::getShortProgramName()
|
||||
*/
|
||||
|
||||
inline const char *Os::getProgramName(void)
|
||||
{
|
||||
return programName;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return the short name of the running executable.
|
||||
*
|
||||
* The program name will not include the path, but will just be the file name.
|
||||
*
|
||||
* @return The short name of the running executable
|
||||
* @see Os::getProgramName()
|
||||
*/
|
||||
|
||||
inline const char *Os::getShortProgramName(void)
|
||||
{
|
||||
return shortProgramName;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Cause Os::abort() to return instead of abort the process.
|
||||
*
|
||||
* This routine should not be called directly by users.
|
||||
*
|
||||
* This routine is provided so that structured exception handling can catch
|
||||
* an exception, call Fatal to run the ExitChain, and rethrow the exception
|
||||
* so that the debugger will catch it.
|
||||
*/
|
||||
|
||||
inline void Os::returnFromAbort(void)
|
||||
{
|
||||
shouldReturnFromAbort = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Check if the Os knows the game needs to shut down.
|
||||
*
|
||||
* The Os can decide that the game need to end for a number of reasons,
|
||||
* including closing the application or shutting the machine down.
|
||||
*
|
||||
* @return True if the game should quit, otherwise false
|
||||
*/
|
||||
|
||||
inline bool Os::isGameOver(void)
|
||||
{
|
||||
return gameOver;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return the number of updates that the have occurred.
|
||||
*
|
||||
* @return This value is updated during the Os::update() routine.
|
||||
*/
|
||||
|
||||
inline int Os::getNumberOfUpdates(void)
|
||||
{
|
||||
return numberOfUpdates;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Indicate whether or not the application was paused.
|
||||
*
|
||||
* @return True if the application was in the background (paused), otherwise false
|
||||
*/
|
||||
|
||||
inline bool Os::wasApplicationPaused(void)
|
||||
{
|
||||
return wasPaused;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return a flag indicating whether we are running a multiprocessor machine or not.
|
||||
*
|
||||
* @return True if the machine has more than one processor, false if not.
|
||||
*/
|
||||
|
||||
inline bool Os::isMultiprocessor(void)
|
||||
{
|
||||
return isMp;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Return the number of processors.
|
||||
*
|
||||
* @return The number of processors in the machine.
|
||||
*/
|
||||
|
||||
inline int Os::getProcessorCount(void)
|
||||
{
|
||||
return processorCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline bool Os::wasFocusLost()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void Os::setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void Os::setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline void Os::setQueueKeyDownHookFunction(QueueKeyDownHookFunction)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PerThreadData.cpp
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/PerThreadData.h"
|
||||
|
||||
#include "sharedSynchronization/Gate.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
pthread_key_t PerThreadData::slot;
|
||||
bool PerThreadData::slotCreated=false;
|
||||
|
||||
// ======================================================================
|
||||
// Install the per-thread-data subsystem
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// This routine will install the per-thread-data subsystem that is required for several
|
||||
// other subsystems in the engine. It should be called from the primary thread before
|
||||
// any other threads have been created. It will also call threadInstall() for the
|
||||
// primary thread.
|
||||
//
|
||||
// See Also:
|
||||
//
|
||||
// PerThreadData::remove()
|
||||
|
||||
void PerThreadData::install(void)
|
||||
{
|
||||
if (pthread_key_create(&slot, 0)!=0)
|
||||
{
|
||||
FATAL(true, ("pthread_key_create failed"));
|
||||
}
|
||||
slotCreated=true;
|
||||
|
||||
threadInstall();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Remove the per-thread-subsystem.
|
||||
*
|
||||
* This routine should be called by the primary thread after all other threads have
|
||||
* terminated, and no other uses of per-thread-data will occur.
|
||||
*
|
||||
* @see PerThreadData::install()
|
||||
*/
|
||||
|
||||
void PerThreadData::remove(void)
|
||||
{
|
||||
threadRemove();
|
||||
|
||||
if (pthread_key_delete(slot)!=0)
|
||||
{
|
||||
FATAL(true, ("pthread_key_delete failed"));
|
||||
}
|
||||
|
||||
slotCreated=false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get access to the per-thread-data.
|
||||
*
|
||||
* This routine will verify the per-thread-data subsystem has been installed and the
|
||||
* threadInstall() function has been called for the current thread.
|
||||
*
|
||||
* @return A pointer to the per-thread-data.
|
||||
*/
|
||||
|
||||
PerThreadData::Data *PerThreadData::getData(bool allowReturnNull)
|
||||
{
|
||||
UNREF(allowReturnNull);
|
||||
|
||||
if (!slotCreated)
|
||||
{
|
||||
DEBUG_FATAL(true && !allowReturnNull, ("not installed"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Data * const data = reinterpret_cast<Data *>(pthread_getspecific(slot));
|
||||
DEBUG_FATAL(!data && !allowReturnNull, ("not installed for this thread"));
|
||||
return data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Create the per-thread-data for a new thread.
|
||||
*
|
||||
* This routine should be called in a thread before the first usage of per-thread-data.
|
||||
*
|
||||
* If the client is calling this function on a thread that existed before the engine was
|
||||
* installed, the client should set isNewThread to false. Setting isNewThread to false
|
||||
* prevents the function from validating that the thread's TLS is NULL. For threads existing
|
||||
* before the engine is installed, the TLS data for the thread is undefined.
|
||||
*
|
||||
* @param isNewThread [IN] true if the thread was created after the engine was installed, false otherwise
|
||||
* @see PerThreadData::threadRemove()
|
||||
*/
|
||||
|
||||
void PerThreadData::threadInstall(bool isNewThread)
|
||||
{
|
||||
UNREF(isNewThread);
|
||||
|
||||
DEBUG_FATAL(!slotCreated, ("not installed"));
|
||||
|
||||
// only check for already-set data if this is supposed to be a new thread
|
||||
DEBUG_FATAL(isNewThread && pthread_getspecific(slot), ("already installed for this thread"));
|
||||
|
||||
// create the data
|
||||
Data * const data = new Data;
|
||||
|
||||
// initialize the data
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
//create the event for file streaming reads
|
||||
data->readGate = new Gate(false);
|
||||
|
||||
// set the data into the thread slot
|
||||
const BOOL result = pthread_setspecific(slot, data);
|
||||
UNREF(result);
|
||||
DEBUG_FATAL(result, ("pthread_setspecific failed")); //NB: unlike Windows, returns 0 on success.
|
||||
} //lint !e429 // Warning -- Custodial pointer 'data' has not been freed or returned) // stored int thread-local-storage
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Destroythe per-thread-data for a terminating thread.
|
||||
*
|
||||
* This routine should be called in a thread after the last usage of per-thread-data.
|
||||
*
|
||||
* @see PerThreadData::threadInstall()
|
||||
*/
|
||||
|
||||
void PerThreadData::threadRemove(void)
|
||||
{
|
||||
DEBUG_FATAL(!slotCreated, ("not installed"));
|
||||
DEBUG_FATAL(!pthread_getspecific(slot), ("thread not installed"));
|
||||
|
||||
// get the data
|
||||
Data *data = getData();
|
||||
|
||||
//close the event used for file streaming reads
|
||||
delete data->readGate;
|
||||
data->readGate = NULL;
|
||||
|
||||
// wipe the data in the thread slot
|
||||
const BOOL result2 = pthread_setspecific(slot, NULL);
|
||||
UNREF(result2);
|
||||
DEBUG_FATAL(result2, ("TlsSetValue failed")); //NB: unlike Windows, returns 0 on success.
|
||||
|
||||
// free the memory
|
||||
delete data;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,232 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// PerThreadData.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef PER_THREAD_DATA_H
|
||||
#define PER_THREAD_DATA_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
|
||||
class Gate;
|
||||
|
||||
// ======================================================================
|
||||
/**
|
||||
* Provide thread local storage functionality.
|
||||
*
|
||||
* This class' purpose is to allow each thread to maintain some storage that is local and private to each thread.
|
||||
* The system must be installed before use. Each thread that may use per-thread-data will also need to call the
|
||||
* threadInstall() routine after creation and threadRemove() just before termination of the thread.
|
||||
*/
|
||||
class PerThreadData
|
||||
{
|
||||
private:
|
||||
|
||||
struct Data
|
||||
{
|
||||
bool exitChainRunning;
|
||||
bool exitChainFataling;
|
||||
ExitChain::Entry *exitChainFirstEntry;
|
||||
|
||||
int debugPrintFlags;
|
||||
|
||||
Gate *readGate;
|
||||
};
|
||||
|
||||
static pthread_key_t slot;
|
||||
static bool slotCreated;
|
||||
|
||||
private:
|
||||
|
||||
static Data *getData(bool allowReturnNull=false);
|
||||
|
||||
private:
|
||||
|
||||
PerThreadData(void);
|
||||
PerThreadData(const PerThreadData &);
|
||||
PerThreadData &operator =(const PerThreadData &);
|
||||
|
||||
public:
|
||||
|
||||
static void install(void);
|
||||
static void remove(void);
|
||||
|
||||
static void threadInstall(bool isNewThread = true);
|
||||
static void threadRemove(void);
|
||||
|
||||
static bool isThreadInstalled(void);
|
||||
|
||||
static bool getExitChainRunning(void);
|
||||
static void setExitChainRunning(bool newValue);
|
||||
|
||||
static bool getExitChainFataling(void);
|
||||
static void setExitChainFataling(bool newValue);
|
||||
|
||||
static ExitChain::Entry *getExitChainFirstEntry(void);
|
||||
static void setExitChainFirstEntry(ExitChain::Entry *newValue);
|
||||
|
||||
static int getDebugPrintFlags(void);
|
||||
static void setDebugPrintFlags(int newValue);
|
||||
|
||||
static Gate *getFileStreamerReadGate(void);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
/**
|
||||
* Determine if the per-thread-data is available for this thread
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* True if the per-thread-data is installed correctly, false otherwise
|
||||
*
|
||||
* Remarks:
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
*
|
||||
* -TRF- looks like Win98 does not zero out a new TLS slot for
|
||||
* threads existing at the time of slot creation. Thus, if you build a
|
||||
* plugin that only initializes the engine the first time it is
|
||||
* used, and other threads already exist in the app, those threads
|
||||
* will contain bogus non-null data in the TLS slot. If the plugin really
|
||||
* wants to do lazy initialization of the engine, it will need
|
||||
* to handle calling PerThreadData::threadInstall() for all existing threads
|
||||
* (except the thread that initialized the engine, which already
|
||||
* has its PerThreadData::threadInstall() called).
|
||||
*/
|
||||
|
||||
inline bool PerThreadData::isThreadInstalled(void)
|
||||
{
|
||||
return (getData(true) != NULL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get the exit chain running flag value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
*
|
||||
* @return True if the exit chain is running, false otherwise.
|
||||
* @see ExitChain::isRunning()
|
||||
*/
|
||||
|
||||
inline bool PerThreadData::getExitChainRunning(void)
|
||||
{
|
||||
return getData()->exitChainRunning;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Set the exit chain running flag value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
*
|
||||
* @param newValue New value for the exit chain running flag
|
||||
*/
|
||||
|
||||
inline void PerThreadData::setExitChainRunning(bool newValue)
|
||||
{
|
||||
getData()->exitChainRunning = newValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get the exit chain fataling flag value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
*
|
||||
* @return True if the exit chain is fataling, false otherwise.
|
||||
* @see ExitChain::isFataling()
|
||||
*/
|
||||
|
||||
inline bool PerThreadData::getExitChainFataling(void)
|
||||
{
|
||||
return getData()->exitChainFataling;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Set the exit chain fataling flag value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
*
|
||||
* @param newValue New value for the exit chain fataling flag
|
||||
*/
|
||||
|
||||
inline void PerThreadData::setExitChainFataling(bool newValue)
|
||||
{
|
||||
getData()->exitChainFataling = newValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get the first entry for the exit chain.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
* This routine may return NULL.
|
||||
*
|
||||
* @return Pointer to the first entry on the exit chain
|
||||
* @see ExitChain::isFataling()
|
||||
*/
|
||||
|
||||
inline ExitChain::Entry *PerThreadData::getExitChainFirstEntry(void)
|
||||
{
|
||||
return getData()->exitChainFirstEntry;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Set the exit chain fataling flag value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the ExitChain class.
|
||||
* The parameter to this routine may be NULL.
|
||||
*
|
||||
* @param newValue New value for the exit chain first entry
|
||||
*/
|
||||
|
||||
inline void PerThreadData::setExitChainFirstEntry(ExitChain::Entry *newValue)
|
||||
{
|
||||
getData()->exitChainFirstEntry = newValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Get the debug print flags.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
|
||||
*
|
||||
* @return Current value of the debug print flags
|
||||
*/
|
||||
|
||||
inline int PerThreadData::getDebugPrintFlags(void)
|
||||
{
|
||||
return getData()->debugPrintFlags;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Set the debug print flags value.
|
||||
*
|
||||
* This routine is not intended for general use; it should only be used by the DebugPrint functions.
|
||||
*/
|
||||
|
||||
inline void PerThreadData::setDebugPrintFlags(int newValue)
|
||||
{
|
||||
getData()->debugPrintFlags = newValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline Gate *PerThreadData::getFileStreamerReadGate(void)
|
||||
{
|
||||
return getData()->readGate;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,273 @@
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/PlatformGlue.h"
|
||||
#include <ctime>
|
||||
|
||||
|
||||
real abs(real x)
|
||||
{
|
||||
return fabs(x);
|
||||
}
|
||||
|
||||
int _stricmp(const char* string1, const char* string2)
|
||||
{
|
||||
int first, second;
|
||||
|
||||
do
|
||||
{
|
||||
first = toupper(*string1);
|
||||
second = toupper(*string2);
|
||||
string1++;
|
||||
string2++;
|
||||
} while (first && first==second);
|
||||
|
||||
return (first - second);
|
||||
}
|
||||
|
||||
char* _itoa(int value, char* stringOut, int radix)
|
||||
{
|
||||
DEBUG_FATAL((radix != 10), ("itoa only supprts base 10"));
|
||||
sprintf(stringOut, "%d", value);
|
||||
return stringOut;
|
||||
}
|
||||
|
||||
bool QueryPerformanceCounter(__int64* time)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
*time = static_cast<LARGE_INTEGER>(tv.tv_sec);
|
||||
*time = (*time * 1000000) + static_cast<LARGE_INTEGER>(tv.tv_usec);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool QueryPerformanceFrequency(__int64 *freq)
|
||||
{
|
||||
*freq = CLOCKS_PER_SEC;
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
void Sleep(DWORD msecs)
|
||||
{
|
||||
//Sleep takes a time to sleep in milliseconds.
|
||||
usleep(msecs*1000); //usleep works with microseconds
|
||||
}
|
||||
|
||||
int GetLastError()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
void OutputDebugString(const char* stringOut)
|
||||
{
|
||||
fprintf(stderr,"%s",stringOut);
|
||||
}
|
||||
|
||||
|
||||
//File Support
|
||||
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if(unsup)
|
||||
return FALSE; //Windows doesn't support this overrlap buffer
|
||||
|
||||
retval = fwrite(lpBuffer, sizeof(char), numBytesToWrite, hFile);
|
||||
*numBytesWritten = retval;
|
||||
return (retval < 0) ? FALSE : TRUE;
|
||||
|
||||
}
|
||||
|
||||
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToRead, DWORD* numBytesRead, void* unsup)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if(unsup)
|
||||
return FALSE; //Windows doesn't support this overrlap buffer
|
||||
|
||||
retval = fread(lpBuffer, sizeof(char), numBytesToRead, hFile);
|
||||
*numBytesRead = retval;
|
||||
return (retval <= 0) ? FALSE : TRUE;
|
||||
|
||||
}
|
||||
|
||||
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod)
|
||||
{
|
||||
//Mimics the Win32 function to set the position of a file pointer. return -1 on failure else current position.
|
||||
|
||||
int retval;
|
||||
retval = fseek(hFile, lDistanceToMove, dwMoveMethod);
|
||||
|
||||
return (retval == 0) ? ftell(hFile) : -1;
|
||||
}
|
||||
|
||||
//TODO Consider using a call to open() instead of fopen() to get a better mapping of parameters to Win32
|
||||
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsupB)
|
||||
{
|
||||
FILE* retval = 0;
|
||||
|
||||
DEBUG_FATAL(flagsAndAttributes != FILE_ATTRIBUTE_NORMAL, ("Unsupported File mode call to CreateFile()"));
|
||||
DEBUG_FATAL(unsupB != NULL, ("Unsupported File mode call to CreateFile()"));
|
||||
//DEBUG_FATAL(shareMode != 0, ("Unsupported File mode call to CreateFile()"));
|
||||
DEBUG_FATAL(unsupA != 0, ("Unsupported File mode call to CreateFile()"));
|
||||
|
||||
switch(creationDisposition)
|
||||
{
|
||||
case CREATE_NEW:
|
||||
retval = fopen(fileName, "r");
|
||||
if (retval)
|
||||
{
|
||||
fclose(retval);
|
||||
retval = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(retval);
|
||||
retval = fopen(fileName, "w");
|
||||
}
|
||||
break;
|
||||
|
||||
case CREATE_ALWAYS:
|
||||
retval = fopen(fileName, "w");
|
||||
break;
|
||||
|
||||
case OPEN_EXISTING:
|
||||
retval = fopen(fileName, "r");
|
||||
if ((access & GENERIC_WRITE) && retval)
|
||||
{
|
||||
fclose(retval);
|
||||
retval = fopen(fileName, "a");
|
||||
rewind(retval);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPEN_ALWAYS:
|
||||
if (access & GENERIC_WRITE)
|
||||
{
|
||||
retval = fopen(fileName, "a");
|
||||
rewind(retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = fopen(fileName, "r");
|
||||
}
|
||||
break;
|
||||
|
||||
case TRUNCATE_EXISTING:
|
||||
DEBUG_FATAL(!(access & GENERIC_WRITE),("Must open truncate file with write access"));
|
||||
retval = fopen(fileName, "w");
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
BOOL CloseHandle(FILE* hFile)
|
||||
{
|
||||
int retval = fclose(hFile);
|
||||
return (retval == 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
//TODO There must be a more elegant UNIX command to get file size...fstat() needs filename
|
||||
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize)
|
||||
{
|
||||
long int curPos;
|
||||
DWORD endPos;
|
||||
curPos = ftell(hFile);
|
||||
fseek(hFile, 0, SEEK_END);
|
||||
endPos = ftell(hFile);
|
||||
fseek(hFile, curPos, SEEK_SET);
|
||||
return endPos;
|
||||
|
||||
#if 0
|
||||
//This is what I want to do, but I have no file des number
|
||||
struct stat buf;
|
||||
fstat(hFile, &buf);
|
||||
return buf->st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL FileExists(const char* filename)
|
||||
{
|
||||
BOOL retval = false;
|
||||
|
||||
struct stat info;
|
||||
if (stat(filename, &info) == 0)
|
||||
{
|
||||
if (S_ISREG(info.st_mode))
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Memory Functions
|
||||
|
||||
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect)
|
||||
{
|
||||
if (location)
|
||||
return location;
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
BOOL VirtualFree(void* location, DWORD size, DWORD freeType)
|
||||
{
|
||||
free(location);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect)
|
||||
{
|
||||
//Unused. Function stub for compatibility
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL IsBadReadPtr(const void* location, unsigned int size)
|
||||
{
|
||||
//unused
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void MessageBox (void* unused, const char* message, const char* unused2, int flags)
|
||||
{
|
||||
OutputDebugString(message);
|
||||
}
|
||||
|
||||
char *ConvertCommandLine(int argc, char ** argv)
|
||||
{
|
||||
static char buffer[2048];
|
||||
|
||||
int totalSize=0;
|
||||
for (int i=0; i<argc; ++i)
|
||||
{
|
||||
totalSize+=strlen(argv[i])+1;
|
||||
}
|
||||
|
||||
if(totalSize>1023)
|
||||
{
|
||||
int argIndex = 0;
|
||||
fprintf(stderr, "Exceeded command line args length of %d. Total size is %d\n", sizeof(buffer), totalSize);
|
||||
for(argIndex = 0; argIndex < argc; ++argIndex)
|
||||
{
|
||||
fprintf(stderr, "argv[%d]=\"%s\"\n", argIndex, argv[argIndex]);
|
||||
}
|
||||
FATAL(true,("Command line exceeds maximum length."));
|
||||
}
|
||||
|
||||
buffer[0]='\0';
|
||||
|
||||
for (int i=0; i<argc; ++i)
|
||||
{
|
||||
strcat(buffer,argv[i]);
|
||||
if (i!=argc-1)
|
||||
{
|
||||
strcat(buffer," ");
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#ifndef INCLUDED_MISC_H
|
||||
#define INCLUDED_MISC_H
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef unsigned short int WORD;
|
||||
typedef unsigned long int DWORD;
|
||||
typedef bool BOOL;
|
||||
typedef long long __int64; //lint !e13 !e19 // Error: 13 (Bad type), Error: 19 (Useless declaration) // -TRF- Lint preprocessor discrepency, @todo look into this.
|
||||
typedef __int64 LARGE_INTEGER;
|
||||
|
||||
const BOOL FALSE = 0;
|
||||
const BOOL TRUE = 1;
|
||||
|
||||
|
||||
float abs(float x);
|
||||
int _stricmp(const char* string1, const char* string2);
|
||||
|
||||
//String to numeric conversions
|
||||
char* _itoa(int value, char* stringOut, int radix);
|
||||
|
||||
//Format specifier for non-portable printf
|
||||
#define UINT64_FORMAT_SPECIFIER "%llu"
|
||||
#define INT64_FORMAT_SPECIFIER "%lli"
|
||||
|
||||
//Constant definition macro for 64 bit values
|
||||
#define UINT64_LITERAL(a) a ## ull
|
||||
#define INT64_LITERAL(a) a ## ll
|
||||
|
||||
bool QueryPerformanceCounter(__int64 *time);
|
||||
bool QueryPerformanceFrequency(__int64 *freq);
|
||||
void Sleep(DWORD msecs);
|
||||
int GetLastError();
|
||||
void OutputDebugString(const char* stringOut);
|
||||
|
||||
//File Support
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef FILE* HANDLE;
|
||||
|
||||
#define INVALID_HANDLE_VALUE NULL //Have to use a #define because this may be a FILE*
|
||||
|
||||
|
||||
const int GENERIC_READ = 1 << 0;
|
||||
const int GENERIC_WRITE = 1 << 1;
|
||||
|
||||
const int CREATE_NEW = 1;
|
||||
const int CREATE_ALWAYS = 2;
|
||||
const int OPEN_EXISTING = 3;
|
||||
const int OPEN_ALWAYS = 4;
|
||||
const int TRUNCATE_EXISTING = 5;
|
||||
|
||||
const DWORD FILE_ATTRIBUTE_NORMAL = 1;
|
||||
|
||||
const int FILE_CURRENT = SEEK_CUR;
|
||||
const int FILE_BEGIN = SEEK_SET;
|
||||
const int FILE_END = SEEK_END;
|
||||
|
||||
const int FILE_SHARE_READ = 1;
|
||||
|
||||
BOOL WriteFile(FILE* hFile, const void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesWritten, void* unsup=NULL);
|
||||
BOOL ReadFile(FILE* hFile, void* lpBuffer, DWORD numBytesToWrite, DWORD* numBytesRead, void* unsup=NULL);
|
||||
DWORD SetFilePointer(FILE* hFile, long lDistanceToMove, long* lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
FILE* CreateFile(const char* fileName, DWORD access, DWORD shareMode, void* unsupA, DWORD creationDisposition, DWORD flagsAndAttributes, FILE* unsup2);
|
||||
BOOL CloseHandle(FILE* hFile);
|
||||
DWORD GetFileSize(FILE* hFile, DWORD* lpHighSize);
|
||||
BOOL FileExists(const char* fileName);
|
||||
|
||||
|
||||
//Memory Support
|
||||
|
||||
const int MEM_RESERVE = 0;
|
||||
const int MEM_COMMIT = 1;
|
||||
const int PAGE_READWRITE = 0;
|
||||
const int MEM_RELEASE = 0;
|
||||
const int PAGE_NOACCESS = 0;
|
||||
|
||||
void* VirtualAlloc(void* location, DWORD size, DWORD flAllocationType, DWORD flProtect);
|
||||
BOOL VirtualFree(void* location, DWORD size, DWORD freeType);
|
||||
BOOL VirtualProtect(void* location, DWORD size, DWORD newProtect, DWORD* oldProect);
|
||||
BOOL IsBadReadPtr(const void* location, unsigned int size);
|
||||
|
||||
//Misc output stuff
|
||||
|
||||
const int MB_OK = 0;
|
||||
const int MB_ICONEXCLAMATION = 1;
|
||||
void MessageBox (void* unused, const char* message, const char* unused2, int flags);
|
||||
char *ConvertCommandLine(int argc, char ** argv);
|
||||
|
||||
//String functions
|
||||
#define _vsnprintf vsnprintf
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
inline int _strnicmp (const char * a, const char * b, size_t count)
|
||||
{
|
||||
return ::strncasecmp (a, b, count);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
inline int _open(const char *filename, int oflag) { return open(filename, oflag); }
|
||||
inline int _open(const char *filename, int oflag, mode_t pmode) { return open(filename, oflag, pmode); }
|
||||
inline int _creat(const char *filename, mode_t pmode) { return creat(filename, pmode); }
|
||||
inline int _close(int fd) { return close(fd); }
|
||||
inline int _write(int fd, const void *buffer, unsigned int count) { return write(fd, buffer, count); }
|
||||
inline int _dup(int fd) { return dup(fd); }
|
||||
inline int _dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); }
|
||||
inline long _lseek(int fd, long offset, int origin) { return lseek(fd, offset, origin); }
|
||||
inline int _read(int fd, void *buffer, unsigned int count) { return read(fd, buffer, count); }
|
||||
inline long _tell(int fd) { return _lseek(fd,0,SEEK_CUR); }
|
||||
inline int _umask(int pmode) { return umask(pmode); }
|
||||
inline int _unlink(const char *pathname) { return unlink(pathname); }
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
#endif //INCLUDED_MISC_H
|
||||
@@ -0,0 +1,185 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedFoundation.cpp
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001 - 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/SetupSharedFoundation.h"
|
||||
|
||||
#include "sharedDebug/ConfigSharedDebugLinux.h"
|
||||
#include "sharedDebug/DebugMonitor.h"
|
||||
#include "sharedDebug/Profiler.h"
|
||||
#include "sharedFoundation/Clock.h"
|
||||
#include "sharedFoundation/CommandLine.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
#include "sharedFoundation/ConfigSharedFoundation.h"
|
||||
#include "sharedFoundation/CrcLowerString.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/Os.h"
|
||||
#include "sharedFoundation/PerThreadData.h"
|
||||
#include "sharedFoundation/StaticCallbackEntry.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <math.h>
|
||||
|
||||
// ======================================================================
|
||||
/**
|
||||
* Install the engine.
|
||||
*
|
||||
* The settings in the Data structure will determine which subsystems
|
||||
* get initialized.
|
||||
*/
|
||||
|
||||
void SetupSharedFoundation::install(const Data &data)
|
||||
{
|
||||
// and get the command line stuff in quick so we can make decisions based on the command line settings
|
||||
CommandLine::install();
|
||||
ConfigFile::install();
|
||||
|
||||
if (data.lpCmdLine)
|
||||
CommandLine::absorbString(data.lpCmdLine);
|
||||
if (data.argc)
|
||||
CommandLine::absorbStrings(const_cast<const char**>(data.argv+1), data.argc-1);
|
||||
|
||||
#if 0
|
||||
//currently there's a problem that we cannot override the defaults here.
|
||||
if (data.configFile)
|
||||
IGNORE_RETURN(ConfigFile::loadFile(data.configFile));
|
||||
#endif
|
||||
|
||||
// get the post command-line text for the ConfigFile (key-value pairs)
|
||||
const char *configString = CommandLine::getPostCommandLineString();
|
||||
if (configString)
|
||||
ConfigFile::loadFromCommandLine(configString);
|
||||
|
||||
//@todo there is a lot of stuff in win32 setup not here...like exitchain
|
||||
Profiler::registerDebugFlags();
|
||||
#if _DEBUG
|
||||
MemoryManager::registerDebugFlags();
|
||||
#endif//_DEBUG
|
||||
|
||||
// Setup Linux DebugMonitor support.
|
||||
// @todo fix this dependency: DebugMonitor really should be moved into Foundation the way things currently are. TRF is following the existing win32 setup.
|
||||
#ifdef _DEBUG
|
||||
ConfigSharedDebugLinux::install();
|
||||
DebugMonitor::install();
|
||||
#endif
|
||||
|
||||
// setup the engine configuration
|
||||
ConfigSharedFoundation::Defaults defaults;
|
||||
defaults.frameRateLimit = data.frameRateLimit;
|
||||
ConfigSharedFoundation::install(defaults);
|
||||
SetWarningStrictFatal(ConfigFile::getKeyBool("SharedDebug", "strict", false));
|
||||
Report::install();
|
||||
Clock::install(data.runInBackground, false);
|
||||
|
||||
PersistentCrcString::install();
|
||||
CrcLowerString::install();
|
||||
StaticCallbackEntry::install();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Call a function with appropriate exception handling (not)
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// this is stubbed and exception handling is ignored currently
|
||||
|
||||
void SetupSharedFoundation::callbackWithExceptionHandling(
|
||||
void (*callback)(void) // Routine to call with exception handling
|
||||
)
|
||||
{
|
||||
if (ConfigSharedFoundation::getNoExceptionHandling())
|
||||
{
|
||||
callback();
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
try
|
||||
{
|
||||
callback();
|
||||
}
|
||||
catch (__exception * mathException)
|
||||
{
|
||||
FATAL(true, ("Math Exception: %s\n", mathException->name));
|
||||
}
|
||||
catch (const char* message)
|
||||
{
|
||||
FATAL(true, ("Character Exception: %s\n", message));
|
||||
}
|
||||
catch(std::exception & m)
|
||||
{
|
||||
const char * c = m.what();
|
||||
FATAL(true, ("Std::exception: %s\n", c));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FATAL(true, ("Unknown exception\n"));
|
||||
}
|
||||
#else
|
||||
callback();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Uninstall the engine.
|
||||
*
|
||||
* This routine will properly uninstall the engine componenets that were
|
||||
* installed by SetupSharedFoundation::install().
|
||||
*/
|
||||
|
||||
void SetupSharedFoundation::remove(void)
|
||||
{
|
||||
ExitChain::quit();
|
||||
|
||||
if (GetNumberOfWarnings())
|
||||
REPORT(true, Report::RF_print | Report::RF_log | Report::RF_dialog, ("%d warnings logged", GetNumberOfWarnings()));
|
||||
|
||||
// this routine can't be on the exit chain because the exit chain depends upon the PerThreadData class being around
|
||||
//PerThreadData::remove();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
SetupSharedFoundation::Data::Data(Defaults defaults)
|
||||
{
|
||||
Zero(*this);
|
||||
|
||||
switch (defaults)
|
||||
{
|
||||
case D_game:
|
||||
runInBackground = true;
|
||||
|
||||
lpCmdLine = NULL;
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
|
||||
configFile = NULL;
|
||||
|
||||
frameRateLimit = CONST_REAL(0);
|
||||
break;
|
||||
|
||||
case D_console:
|
||||
runInBackground = true;
|
||||
|
||||
lpCmdLine = NULL;
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
|
||||
configFile = NULL;
|
||||
|
||||
frameRateLimit = CONST_REAL(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_FATAL(true, ("unknown case"));
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,58 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedFoundation.h
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
// copyright 2001 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_SetupSharedFoundation_H
|
||||
#define INCLUDED_SetupSharedFoundation_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
struct DebugMenuEntry;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class SetupSharedFoundation
|
||||
{
|
||||
public:
|
||||
|
||||
struct Data
|
||||
{
|
||||
// allow running in background
|
||||
bool runInBackground;
|
||||
|
||||
// pointer to command line
|
||||
char* lpCmdLine;
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
const char *configFile;
|
||||
|
||||
real frameRateLimit;
|
||||
|
||||
public:
|
||||
|
||||
enum Defaults
|
||||
{
|
||||
D_game,
|
||||
D_console
|
||||
};
|
||||
|
||||
Data(Defaults defaults);
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static void install(const Data &data);
|
||||
static void remove(void);
|
||||
|
||||
static void callbackWithExceptionHandling(void (*callback)(void));
|
||||
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// vsnprintf.cpp
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
#include "sharedFoundation/vsnprintf.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
// ======================================================================
|
||||
// Format a printf-style string into a text buffer of fixed size
|
||||
//
|
||||
// Return value:
|
||||
//
|
||||
// The number of characters written into the buffer, or -1 if the buffer was too small
|
||||
//
|
||||
// Remarks:
|
||||
//
|
||||
// If the buffer would overflow, the null terminating character is not written and -1
|
||||
// will be returned.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
int vsnprintf(char *buffer, size_t count, const char *format, va_list va)
|
||||
{
|
||||
return _vsnprintf(buffer, count, format, va);
|
||||
}
|
||||
|
||||
#endif
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,24 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// vsnprintf.h
|
||||
// jeff grills
|
||||
//
|
||||
// copyright 1998 Bootprint Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef VSNPRINTF_H
|
||||
#define VSNPRINTF_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
int vsnprintf(char *buffer, size_t count, const char *format, va_list va);
|
||||
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user