This commit is contained in:
thug1src 2016-02-14 08:39:12 +11:00
commit d8eb714766
1309 changed files with 588460 additions and 0 deletions

145
Code/Core/Debug.h Normal file
View File

@ -0,0 +1,145 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** Created: 05/27/99 mjb **
** **
** File name: core/debug.h **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_H
#define __CORE_DEBUG_H
#ifdef __NOPT_DEBUG__
// for now - always turn on messages and assertion
#define __NOPT_MESSAGES__
#define __NOPT_ASSERT__
#else
// Mick - added assertions always on, regardless of debug mode.
#define __NOPT_ASSERT__
// Gary - ... unless you're working on the tools,
// in which case the asserts prevent the code from compiling...
#ifdef __PLAT_WN32__
#ifndef _CONSOLE // Ken: Asserts now compile for console apps. (see levelassetlister project)
#undef __NOPT_ASSERT__
#endif
#endif
#endif // __NOPT_DEBUG__
#ifdef __NOPT_CDROM__OLD
#undef __NOPT_ASSERT__
#endif
// Temporary switch off assertions flag
#ifdef __NOPT_NOASSERTIONS__
#undef __NOPT_ASSERT__
#endif
// no assertions on final build ("final=")
#ifdef __NOPT_FINAL__
#undef __NOPT_ASSERT__
#endif
#ifdef __NOPT_ASSERT__
#define __DEBUG_CODE__
#endif
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <sys/mem/memdbg.h>
#include "debug/messages.h"
#include "debug/checks.h"
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Dbg
{
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Type Defines **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
void SetUp( void );
void CloseDown( void );
#ifdef __NOPT_FULL_DEBUG__
void* NewClassNode( size_t size );
void DeleteClassNode( void* pMem );
void* NewInstanceNode( size_t size );
void DeleteInstanceNode( void* pMem );
#endif // __NOPT_FULL_DEBUG__
/*****************************************************************************
** Macros **
*****************************************************************************/
#define Dbg_Code(X) X
/*****************************************************************************
** Stubs **
*****************************************************************************/
#else // __NOPT_DEBUG__
#ifndef __NOPT_ASSERT__
inline void SetUp( void ) {};
inline void CloseDown( void ) {};
#else
void SetUp( void );
void CloseDown( void );
#endif // __NOPT_ASSERT
#define Dbg_Code(X)
#endif // __NOPT_DEBUG__
} // namespace Dbg
#endif // __CORE_DEBUG_H

314
Code/Core/Debug/Assert.cpp Normal file
View File

@ -0,0 +1,314 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: assert.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Assert support code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <stdio.h>
#include <core/defines.h>
#include <core/support.h>
#include <core/debug.h>
#include <sys/config/config.h>
#ifndef __PLAT_WN32__
#include <gfx/gfxman.h>
#endif // __PLAT_WN32__
#ifdef __PLAT_NGPS__
int DumpUnwindStack( int iMaxDepth, int *pDest );
#include <libdev.h>
#endif
#ifdef __PLAT_NGC__
#include <dolphin.h>
#define _output OSReport
#else
#define _output printf
#endif
#ifdef __NOPT_ASSERT__
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
static const int vASSERT_BUFFER_SIZE = 512;
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
static AssertTrap* assert_trap_handler = NULL;
static bool screen_assert_active = false;
// made public for Dbg_ Macros
char* msg_null_pointer = "Null Pointer";
char* msg_misaligned_pointer = "Pointer not aligned";
char* msg_pointer_to_free_mem = "Pointer to free mem";
char* msg_unknown_reason = "No reason supplied";
char* msg_type_mismatch = "Type Mismatch: \"%s\" is of type \"%s\" - not a valid \"%s\"";
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
void set_trap( AssertTrap* trap )
{
assert_trap_handler = trap;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void screen_assert( bool on )
{
screen_assert_active = on;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#ifdef __NOPT_DEBUG__
void Assert( char* file, uint line, Signature& sig, char* reason )
#else
void Assert( char* file, uint line, char* reason )
#endif
{
static char assert_buffer1[vASSERT_BUFFER_SIZE];
#ifdef __NOPT_DEBUG
static char assert_buffer2[vASSERT_BUFFER_SIZE];
#endif
static char assert_buffer3[vASSERT_BUFFER_SIZE];
static char* tmp1 = assert_buffer1;
#ifdef __NOPT_DEBUG
static char* tmp2 = assert_buffer2;
#endif
static char* tmp3 = assert_buffer3;
#if !( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
static int again = 0;
if (again)
{
_output ("MEM CONTEXT: %s\n",Mem::Manager::sHandle().GetContextName());
_output( "LOOPED ASSERTION: %s(%d)\n%s\n\n",
file, line, reason );
_output ("Real Assertion: %s\n%s\n",tmp1,tmp3);
while (1); // and hang...
}
again = 1;
_output ("\n--------------------------------------------------\nPLEASE COPY FROM A FEW LINES ABOVE HERE\n\nCURRENT MEM CONTEXT: %s\n\n"
,Mem::Manager::sHandle().GetContextName());
Mem::Manager& mem_man = Mem::Manager::sHandle();
// Mem::Heap* heap = mem_man.TopDownHeap();
// Mem::Region* region = heap->ParentRegion();
// _output ("TopDown Fragmentation %7dK, in %5d Blocks\n",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);
// _output (" used %7dK, in %5d Blocks\n",heap->mUsedMem.m_count / 1024, heap->mUsedBlocks.m_count);
// heap = mem_man.BottomUpHeap();
// _output ("BottomUp Fragmentation %7dK, in %5d Blocks\n",heap->mFreeMem.m_count / 1024, heap->mFreeBlocks.m_count);
// _output (" used %7dK, in %5d Blocks\n",heap->mUsedMem.m_count / 1024, heap->mUsedBlocks.m_count);
// _output ("Shared Region %dK free out of %d K available\n", region->MemAvailable() / 1024, region->TotalSize() / 1024 );
_output("Name Used Frag Free Min Blocks\n");
_output("--------------- ----- ----- ---- ------ ------\n");
Mem::Heap* heap;
for (heap = mem_man.FirstHeap(); heap != NULL; heap = mem_man.NextHeap(heap))
{
Mem::Region* region = heap->ParentRegion();
_output( "%12s: %5dK %4dK %4dK %4dK %5d \n",
heap->GetName(),
heap->mUsedMem.m_count / 1024,
heap->mFreeMem.m_count / 1024,
region->MemAvailable() / 1024,
region->MinMemAvailable() / 1024,
heap->mUsedBlocks.m_count
);
}
_output( "FILE: %s(%d)\nASSERTION: %s\n\n",
file, line, reason );
_output( tmp1, "FILE: %s(%d) ", file, line );
_output( tmp3, "ASSERTION: %s", reason );
// attempt to dump the call stack
// requires that you have the correct .map file, along with the executable
#ifndef __PLAT_WN32__
MemView_FindLeaks();
#endif
_output( "\nCALL STACK ..........................\n\n");
#ifdef __PLAT_NGPS__
DumpUnwindStack( 40, NULL );
#endif
#endif
sprintf( tmp1, "FILE: %s(%d) ", file, line );
sprintf( tmp3, "ASSERTION: %s", reason );
#ifndef __PLAT_NGC__
#ifndef __PLAT_WN32__
// Mick: Attempt to save a screenshot
// Dbg_Printf("Attempting to save screenshot 'screens\\Assert???.bmp'\n");
if (!Config::CD())
{
Gfx::Manager * gfx_manager = Gfx::Manager::Instance();
gfx_manager->ScreenShot( "Assert" );
}
#endif
if ( screen_assert_active )
{
screen_assert_active = false;
#ifndef __PLAT_WN32__
Gfx::Manager* gfx_man = Gfx::Manager::Instance();
gfx_man->AssertText ( 0, tmp1 );
#ifdef __NOPT_DEBUG
sprintf( tmp2, "%s", &sig.GetName() );
gfx_man->AssertText ( 1, tmp2 );
#endif
gfx_man->AssertText ( 2, tmp3 );
gfx_man->AssertFlush();
#endif // __PLAT_WN32__
}
#endif // __PLAT_NGC__
#ifdef __NOPT_DEBUG
sprintf( tmp1, "ASSERTION: %s(%d) %s\n%s\n\n",
file, line, &sig.GetName(), reason );
#else
sprintf( tmp1, "FILE: %s(%d)\nASSERTION: %s\n\n",
file, line, reason );
#endif
#ifdef __PLAT_NGPS__
#if 0 // does not seem to output anything...
sceDevConsInit(); // Initialise screen console output
int console = sceDevConsOpen(
(2048 - 640/2 + 20) << 4, // top left GS X primitive coord
(2048 - 448/2 + 20) << 4, // top left GS Y primitive coord
80, // Number of chars (X)
5); // Number of chars (Y)
sceDevConsAttribute(console, 7); // Output in white (default colours can be
// redefined by sceDevConsSetColor)
sceDevConsClear(console);
sceDevConsPrintf(console, tmp1);
sceDevConsPrintf(console, "blah \n");
sceDevConsPrintf(console, "blah2 \n");
sceDevConsPrintf(console, "blah3 \n");
sceDevConsDraw(console);
#endif
#endif
if ( assert_trap_handler != NULL )
{
_output ("MEM CONTEXT: %s\n",Mem::Manager::sHandle().GetContextName());
Dbg_Printf( "%s\n", tmp1 );
assert_trap_handler( tmp1 );
}
else
{
Dbg_Printf( "%s\n", tmp1 );
Dbg_Printf( "!!NO TRAP HANDLER SET!!\n" );
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
void assert_vcc( char* file, uint line, char* reason )
{
static char assert_buffer[vASSERT_BUFFER_SIZE];
static char* tmp = assert_buffer;
sprintf( tmp, "ASSERTION: %s(%d)\n%s\n\n",
file, line, reason );
if ( assert_trap_handler != NULL )
{
Dbg_Printf( "%s\n", tmp );
assert_trap_handler( tmp );
}
else
{
Dbg_Printf( "%s\n", tmp );
Dbg_Printf( "!!NO TRAP HANDLER SET!!\n" );
}
}
#endif // #ifdef __PLAT_XBOX__
/*****************************************************************************
** Public Functions **
*****************************************************************************/
} // namespace Dbg
#endif //__NOPT_DEBUG__

319
Code/Core/Debug/Checks.h Normal file
View File

@ -0,0 +1,319 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (Dbg_) **
** **
** Created: 05/27/99 mjb **
** **
** File name: core/debug/checks.h **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_CHECKS_H
#define __CORE_DEBUG_CHECKS_H
#ifndef __CORE_DEBUG_LOG_H
#include <core/log.h>
#endif
/*****************************************************************************
** Includes **
*****************************************************************************/
#include "signatrs.h"
#ifdef __NOPT_ASSERT__
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Type Defines **
*****************************************************************************/
typedef void ( AssertTrap ) ( char* message );
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
extern char* msg_unknown_reason; // message strings
extern char* msg_null_pointer;
extern char* msg_misaligned_pointer;
extern char* msg_pointer_to_free_mem;
extern char* msg_type_mismatch;
extern AssertTrap default_trap;
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
#ifdef __NOPT_DEBUG__
void Assert ( char* file, uint line, Signature& sig, char* reason = msg_unknown_reason );
#else
void Assert ( char* file, uint line, char* reason = msg_unknown_reason );
#endif
void pad_printf ( const char* text, ... );
void set_trap( AssertTrap* trap = default_trap );
void screen_assert( bool on = false );
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Dbg
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
#define Dbg_SetTrap(A) { Dbg::set_trap(A); }
#define Dbg_SetScreenAssert(A) { Dbg::screen_assert(A); }
/******************************************************************/
/* Assertions */
/* */
/******************************************************************/
#ifdef __NOPT_DEBUG__
#define Dbg_Assert(_c) \
\
if ( !(_c)) \
{ \
Dbg::Assert( __FILE__, __LINE__, Dbg_signature ); \
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#define Dbg_MsgAssert( _c, _params ) \
\
if( !( _c )) \
{ \
Dbg::pad_printf _params; \
Dbg::Assert( __FILE__, __LINE__, Dbg_signature, \
Dbg::sprintf_pad ); \
}
#else // __NOPT_DEBUG__
// Mick: If we have assertions, but are not in DEBUG mode
// then we don not have the Dbg_signature thing
// so we just pass NULL to assert()
#define Dbg_Assert(_c) \
\
if ( !(_c)) \
{ \
Dbg::Assert ( __FILE__, __LINE__, NULL ); \
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#ifdef __PLAT_WN32__
#ifdef _CONSOLE
#define Dbg_MsgAssert( _c, _params ) \
\
if( !( _c )) \
{ \
printf("\nGame code assert!\n"); \
printf("File %s, line %d\n",__FILE__,__LINE__); \
printf _params; \
printf("\nPress CTRL-C to quit ... "); \
while(1); \
}
#else
#define Dbg_MsgAssert( _c, _params )
#endif
#else
#define Dbg_MsgAssert( _c, _params ) \
\
if( !( _c )) \
{ \
Dbg::pad_printf _params; \
Dbg::Assert( __FILE__, __LINE__, Dbg::sprintf_pad ); \
}
#endif
#endif // __NOPT_DEBUG__
#ifdef __PLAT_NGPS__
#define Dbg_MsgLog( _params ) \
{ \
Dbg::pad_printf _params; \
Log::AddEntry(__FILE__,__LINE__,__PRETTY_FUNCTION__,Dbg::sprintf_pad); \
}
#define Dbg_Log( ) \
{ \
Log::AddEntry(__FILE__,__LINE__,__PRETTY_FUNCTION__); \
}
#else
#define Dbg_MsgLog( _params ) \
{ \
Dbg::pad_printf _params; \
Log::AddEntry(__FILE__,__LINE__,__FUNCTION__,Dbg::sprintf_pad); \
}
#define Dbg_Log( ) \
{ \
Log::AddEntry(__FILE__,__LINE__,__FUNCTION__); \
}
#endif
/******************************************************************/
/* */
/* */
/******************************************************************/
#ifdef __NOPT_MEM_DEBUG__
#define Dbg_AssertPtr(_p) \
{ \
if ((_p) == NULL ) \
{ \
Dbg::Assert ( __FILE__, __LINE__, \
Dbg_signature, Dbg::msg_null_pointer ); \
} \
else if ( *((uint64*)(nAlignDown(_p))) == Mem::vFREE_BLOCK ) \
{ \
Dbg::Assert ( __FILE__, __LINE__, \
Dbg_signature, Dbg::msg_pointer_to_free_mem ); \
} \
}
#else // __NOPT_MEM_DEBUG__
#ifdef __NOPT_DEBUG__
#define Dbg_AssertPtr(_p) \
{ \
if ((_p) == NULL ) \
{ \
Dbg::Assert ( __FILE__, __LINE__, \
Dbg_signature, Dbg::msg_null_pointer ); \
} \
}
#else
#define Dbg_AssertPtr(_p) \
{ \
if ((_p) == NULL ) \
{ \
Dbg::Assert ( __FILE__, __LINE__, \
Dbg::msg_null_pointer ); \
} \
}
#endif //__NOPT_DEBUG__
#endif // __NOPT_MEM_DEBUG__
/******************************************************************/
/* Type Checking */
/* */
/******************************************************************/
#ifdef __NOPT_FULL_DEBUG__
#define Dbg_AssertType(_c,_t) \
{ \
Dbg_AssertPtr(_c); \
Dbg_MsgAssert( nAligned(_c), Dbg::msg_misaligned_pointer ); \
Dbg_MsgAssert(((_c)->classStamp != Spt::Class::vDELETED_CLASS ),"Deleted Class" ); \
Dbg_MsgAssert(((_c)->classStamp == Spt::Class::vREGISTERED_CLASS ), "Corrupt Class" ); \
Dbg_MsgAssert(((_c)->vClassNode()->IsDerivedOrSame(*_t::sClassNode())), \
Dbg::msg_type_mismatch,#_c,(_c)->vClassNode()->GetName(),#_t); \
}
#define Dbg_AssertThis \
{ \
Dbg_AssertPtr(this); \
Dbg_MsgAssert( nAligned(this), Dbg::msg_misaligned_pointer ); \
Dbg_MsgAssert((classStamp != Spt::Class::vDELETED_CLASS ),"Deleted Class" ); \
Dbg_MsgAssert((classStamp == Spt::Class::vREGISTERED_CLASS ), "Corrupt Class" ); \
Dbg_MsgAssert((vClassNode()->IsDerivedOrSame(*sClassNode())), \
Dbg::msg_type_mismatch,"this", vClassNode()->GetName(),sClassNode()->GetName()); \
}
#else // __NOPT_FULL_DEBUG__
#define Dbg_AssertType(_c,_t) Dbg_AssertPtr(_c)
#define Dbg_AssertThis Dbg_AssertPtr(this)
#endif // __NOPT_FULL_DEBUG__
/*****************************************************************************
** Stubs **
*****************************************************************************/
#else
#define Dbg_MsgAssert( _c, _params )
#define Dbg_SetTrap(_f)
#ifdef __NOPT_ASSERT__
#define Dbg_SetScreenAssert(A) { Dbg::screen_assert(A); }
#else
#define Dbg_SetScreenAssert(_b)
#endif
#define Dbg_Assert(_c)
#define Dbg_AssertPtr(_p)
#define Dbg_AssertType(_c,_t)
#define Dbg_AssertThis
#define Dbg_MsgLog( _params )
#define Dbg_Log( )
#endif // __NOPT_ASSERT__
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_DEBUG_CHECKS_H

454
Code/Core/Debug/Debug.cpp Normal file
View File

@ -0,0 +1,454 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: debug.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Debug message support. **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#define __ERROR_STRINGS__
#include <stdio.h>
#include <stdarg.h>
#include <core/defines.h>
#include <core/debug.h>
#include <sys/config/config.h>
#include <sys/timer.h>
#include <sys/mem/memman.h>
#ifdef __PLAT_NGC__
#include <dolphin.h>
#endif __PLAT_NGC__
#ifdef __NOPT_ASSERT__
/*****************************************************************************
** DBG Information **
*****************************************************************************/
Dbg_DefineProject( Core, "Core Library")
namespace Dbg
{
/*****************************************************************************
** Externals **
*****************************************************************************/
extern void set_up ( void );
extern void close_down ( void );
extern OutputCode default_print;
extern AssertTrap default_trap;
/*****************************************************************************
** Defines **
*****************************************************************************/
static const int vBUFFER_SIZE = 512;
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
static char s_sprintf_buffer[vBUFFER_SIZE];
static char s_printf_buffer[vBUFFER_SIZE];
static Flags< Level > s_level_mask = mNONE;
#ifdef __NOPT_DEBUG__
static char* s_typename[] =
{
"ERROR!!",
"WARNING",
"Notify ",
"Message"
};
#endif
static OutputCode* output;
// public for Dbg_ Macros
char* sprintf_pad = s_sprintf_buffer;
char* printf_pad = s_printf_buffer;
#ifdef __NOPT_DEBUG__
Signature* current_sig;
#endif
/*****************************************************************************
** Public Data **
*****************************************************************************/
#ifdef __NOPT_DEBUG__
Project* RegisteredProjects = NULL;
Module* RegisteredModules = NULL;
#endif
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
void print( char* text );
/*****************************************************************************
** Private Functions **
*****************************************************************************/
static void s_prefixed_output( Level level, char* text, va_list args )
{
Dbg_AssertPtr( text );
Dbg_Assert( level >= vERROR );
Dbg_Assert( level <= vMESSAGE );
if ( s_level_mask.Test( level ))
{
return;
}
#ifdef __NOPT_DEBUG__
printf( "[%s] %s - ",
s_typename[level],
&current_sig->GetName());
#endif
vsprintf( printf_pad, text, args);
Dbg::print( printf_pad );
Dbg::print( "\n" );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void pad_printf( const char* text, ... )
{
Dbg_AssertPtr( text );
va_list args;
va_start( args, text );
vsprintf( sprintf_pad, text, args);
va_end( args );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void print( char* text )
{
if ( output )
{
output( text );
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void message ( char *text, ... )
{
Dbg_AssertPtr( text );
if ( s_level_mask.TestMask ( mMESSAGE ))
{
return;
}
va_list args;
va_start( args, text );
s_prefixed_output( vMESSAGE, text, args );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void notify( char *text, ... )
{
Dbg_AssertPtr( text );
if ( s_level_mask.TestMask ( mNOTIFY ))
{
return;
}
va_list args;
va_start( args, text );
s_prefixed_output( vNOTIFY, text, args );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void warning( char *text, ... )
{
Dbg_AssertPtr( text );
if ( s_level_mask.TestMask ( mWARNING ))
{
return;
}
va_list args;
va_start( args, text );
s_prefixed_output( vWARNING, text, args );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void error( char *text, ... )
{
Dbg_AssertPtr( text );
if ( s_level_mask.TestMask ( mERROR ))
{
return;
}
va_list args;
va_start( args, text );
s_prefixed_output( vERROR, text, args );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void set_output( OutputCode* handler )
{
Dbg_AssertPtr( handler );
output = handler;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void level_mask( Flags< Mask > mask )
{
s_level_mask.SetMask( mask );
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
void SetUp( void )
{
set_trap( default_trap );
set_output( Dbg::default_print );
#ifdef __NOPT_DEBUG__
set_up(); // platform specific setup
#endif
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CloseDown( void )
{
#ifdef __NOPT_DEBUG__
close_down(); // platform specific closedown
#endif
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Dbg
#endif // __NOPT_DEBUG__
#ifdef __PLAT_NGPS__
extern "C"
{
int snputs(const char* pszStr);
}
#endif
// Need to do this, cos otherwise the printf inside OurPrintf will get converted to
// an OurPrintf, & it will infinitely recurse.
#undef printf
int OurPrintf ( const char* fmt, ... )
{
// Don't want printf's in some builds.
# if defined( __PLAT_XBOX__ ) && !defined( __NOPT_ASSERT__ )
return 0;
# endif
int ret=-1;
char p_buffer[1024];
char *p_buf = p_buffer;
#if 1
p_buf[0]=0;
#else
sprintf (p_buf,"%6d: ",(int)Tmr::GetRenderFrame());
p_buf+=strlen(p_buf);
#endif
va_list args;
va_start( args, fmt );
vsprintf(p_buf,fmt,args);
va_end( args );
switch (Config::GetHardware())
{
#ifdef __PLAT_NGPS__
case Config::HARDWARE_PS2_PROVIEW:
ret=snputs(p_buffer);
break;
case Config::HARDWARE_PS2_DEVSYSTEM:
case Config::HARDWARE_PS2:
// If we are capturing to a file, then redirect there
if (dumping_printfs == 1)
{
dump_printf(p_buffer);
}
printf("%s",p_buffer);
break;
#endif
#ifdef __PLAT_NGC__
case Config::HARDWARE_NGC:
OSReport("%s",p_buffer);
break;
#endif
#ifdef __PLAT_XBOX__
case Config::HARDWARE_XBOX:
OutputDebugString(p_buffer);
break;
#endif
default:
break;
}
return ret;
}
uint32 quick_check_checksum(uint32 _i, const char *_s, const char *f, int line);
uint32 check_checksum(uint32 _i, const char *_s, const char *f, int line)
{
#ifdef __PLAT_NGPS__
uint32* ra;
asm ( "daddu %0, $31, $0" : "=r" (ra) );
Dbg_MsgAssert(_i == Crc::GenerateCRCFromString(_s),("%s:%d: Checksum 0x%x does not match %s, should be 0x%x",f,line,_i,_s,Crc::GenerateCRCFromString(_s)));
// After the assert has been run once, there is no need to run it again, so
// patch up the calling code to call quick_check_checksum instead
// we just need to inspect the code just before ra,
// make sure it contains the instructions for calling "check_checksum"
// and replace it with the equivalent for "quick_check_checksum"
// This will still all get compiled out for the release build
// but this method lets us validata all usages of CRCD that get called.
// Note, due to I-Cache, this code might still be executed several times
// as the routine will continue to be called until the cache entry for the
// call is overwritten
uint32 JAL_check_checksum = 0x0c000000 + ((uint32)check_checksum >> 2);
uint32 JAL_quick_check_checksum = 0x0c000000 + ((uint32)quick_check_checksum >> 2);
if (ra[-2] == JAL_check_checksum)
{
ra[-2] = JAL_quick_check_checksum;
}
return quick_check_checksum(_i,_s,f,line);
#else
return _i;
#endif
}
uint32 quick_check_checksum(uint32 _i, const char *_s, const char *f, int line)
{
return _i;
}

102
Code/Core/Debug/Mem_stat.h Normal file
View File

@ -0,0 +1,102 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Host (HOST_) **
** **
** File name: core/host.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_MEM_STAT_H
#define __CORE_DEBUG_MEM_STAT_H
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Type Defines **
*****************************************************************************/
class Dbg_MEMORY_STATS
{
public :
Dbg_MEMORY_STATS ( uint total = 0, uint spike = 0,
uint system = 0, uint fixed = 0 );
private :
uint total; // total memory currently allocated on behalf of this module/project
uint spike; // peak total memory allocated on behalf of this module/project
uint system; // current module/project private memory that is adjustable by the user
uint fixed; // current module/project private memory that is a fixed overhead
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline Dbg_MEMORY_STATS::Dbg_MEMORY_STATS ( uint total, uint spike,
uint system, uint fixed )
: total ( total ), spike ( spike ),
system ( system ), fixed ( fixed )
{
}
#endif // __NOPT_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_DEBUG_SIGNATRS_H

199
Code/Core/Debug/Messages.h Normal file
View File

@ -0,0 +1,199 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (Dbg_) **
** **
** File name: core/debug/messages.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_MESSAGES_H
#define __CORE_DEBUG_MESSAGES_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/flags.h>
#include <core/debug/signatrs.h>
#include <core/debug/project.h>
#include <core/debug/module.h>
#ifdef __NOPT_ASSERT__
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Dbg
{
enum Level
{
vERROR,
vWARNING,
vNOTIFY,
vMESSAGE,
vPRINTF
};
enum Mask
{
mERROR = (1<<vERROR),
mWARNING = (1<<vWARNING),
mNOTIFY = (1<<vNOTIFY),
mMESSAGE = (1<<vMESSAGE),
mPRINTF = (1<<vPRINTF),
mALL = ( mERROR |
mWARNING |
mNOTIFY |
mMESSAGE |
mPRINTF ),
mNONE = 0
};
/*****************************************************************************
** Type Defines **
*****************************************************************************/
typedef void ( OutputCode )( char* );
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
extern char* sprintf_pad;
#ifdef __NOPT_DEBUG__
extern Signature* current_sig;
#endif
extern OutputCode default_print;
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
void set_output( OutputCode* handler = default_print );
void level_mask( Flags< Mask > mask );
void message( char* text, ...);
void notify ( char* text, ...);
void warning( char* text, ...);
void error ( char* text, ...);
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
} // namespace Dbg
/*****************************************************************************
** Macros **
*****************************************************************************/
#if (defined ( __PLAT_XBOX__ ) || defined( __PLAT_WN32__ ))
inline void Dbg_SetOutput( const char* A ... ) {};
#define Dbg_LevelMask(A) { Dbg::level_mask(A); }
inline void Dbg_Printf( const char* A ... ) {};
inline void Dbg_Message( const char* A ... ) {};
inline void Dbg_Notify( const char* A ... ) {};
inline void Dbg_Warning( const char* A ... ) {};
inline void Dbg_Error( const char* A ... ) {};
#else
#define Dbg_SetOutput(A...) { Dbg::set_output(##A); }
#define Dbg_LevelMask(A) { Dbg::level_mask(A); }
#ifdef __NOPT_DEBUG__
#define Dbg_Printf(A...) { printf(##A); }
#define Dbg_Message(A...) { Dbg::current_sig = &Dbg_signature; Dbg::message(##A); }
#define Dbg_Notify(A...) { Dbg::current_sig = &Dbg_signature; Dbg::notify(##A); }
#define Dbg_Warning(A...) { Dbg::current_sig = &Dbg_signature; Dbg::warning(##A); }
#define Dbg_Error(A...) { Dbg::current_sig = &Dbg_signature; Dbg::error(##A); }
#else
#define Dbg_Printf(A...) { printf(##A); }
#define Dbg_Message(A...) { Dbg::message(##A); }
#define Dbg_Notify(A...) { Dbg::notify(##A); }
#define Dbg_Warning(A...) { Dbg::warning(##A); }
#define Dbg_Error(A...) { Dbg::error(##A); }
#endif
#endif // __PLAT_XBOX__
/*****************************************************************************
** Stubs **
*****************************************************************************/
#else
#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
inline void Dbg_SetOutput( const char* A ... ) {};
#define Dbg_LevelMask(A)
inline void Dbg_Printf( const char* A ... ) {};
inline void Dbg_Message( const char* A ... ) {};
inline void Dbg_Notify( const char* A ... ) {};
inline void Dbg_Warning( const char* A ... ) {};
inline void Dbg_Error( const char* A ... ) {};
#else
#define Dbg_SetOutput(A...)
#define Dbg_LevelMask(A)
#define Dbg_Printf(A...)
#define Dbg_Message(A...)
#define Dbg_Notify(A...)
#define Dbg_Warning(A...)
#define Dbg_Error(A...)
#endif
#endif // __NOPT_MESSAGES__
/******************************************************************/
/* */
/* */
/******************************************************************/
// A special printf function that only works for Ryan
// (since I love them so much)
#if defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ )
inline void Ryan(const char* A ...) {};
inline void Ken(const char* A ...) {};
inline void Matt(const char* A ...) {};
#else
#ifdef __USER_RYAN__
#define Ryan(A...) printf(##A)
#else
#define Ryan(A...)
#endif
#if defined(__USER_KEN__) && defined(__NOPT_DEBUG__)
#define Ken(A...) printf(##A)
#else
#define Ken(A...)
#endif
#if defined(__USER_MATT__) && defined(__NOPT_DEBUG__)
#define Matt(A...) printf(##A)
#else
#define Matt(A...)
#endif
#endif
#endif // __CORE_DEBUG_MESSAGES_H

183
Code/Core/Debug/Module.h Normal file
View File

@ -0,0 +1,183 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Confidential Information **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (Dbg_) **
** **
** File name: core/debug/module.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_MODULE_H
#define __CORE_DEBUG_MODULE_H
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
#include "mem_stat.h"
/*****************************************************************************
** Defines **
*****************************************************************************/
// Unfortunately, Visual C++ does not support the __PRETTY_FUNCTION__ predefined
// name. The most information we can get at is __FILE__.
#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
#define __PRETTY_FUNCTION__ __FILE__
#endif
/*****************************************************************************
** Type Defines **
*****************************************************************************/
namespace Dbg
{
class Project;
class Module
{
public :
Module ( Project& proj, const char& prefix, const char& description );
void SetNext ( const Module* next );
void SetSibling ( const Module* sibling );
const Module* GetNext ( void ) const;
const Module* GetSibling ( void ) const;
private :
const Module* m_next; // pointer to next registered module
const Module* m_sibling; // pointer to next module in same project
const char& m_prefix; // module prefix
const char& m_description; // module description
Project& m_project; // project that this modules belongs to
Dbg_MEMORY_STATS m_stats;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
extern Module* RegisteredModules;
} // namespace Dbg
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
namespace Dbg
{
inline Module::Module( Project& proj, const char& pref, const char& desc )
: m_prefix ( pref ),
m_description ( desc ),
m_project ( proj )
{
m_next = Dbg::RegisteredModules; // add module to main registration list
Dbg::RegisteredModules = this;
m_sibling = m_project.GetChildren(); // add module to its project parent
m_project.SetChildren( this );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Module::SetNext( const Module* next )
{
m_next = next;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Module::SetSibling( const Module* sibling )
{
m_sibling = sibling;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline const Module* Module::GetNext( void ) const
{
return m_next;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline const Module* Module::GetSibling( void ) const
{
return m_sibling;
}
} // namespace Dbg
/*****************************************************************************
** Stubs **
*****************************************************************************/
#else
#endif //__NOPT_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_DEBUG_MODULE_H

View File

@ -0,0 +1,341 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: p_debug.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Platform specific debug code **
** **
*****************************************************************************/
#include <stdio.h>
#include <core/defines.h>
#include <core/support.h>
#include <core/debug.h>
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Externals **
*****************************************************************************/
extern char _dbg_start[];
extern char _dbg_end[];
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __NOPT_FULL_DEBUG__
enum
{
vMAX_CLASS_NODES = 28000,
vMAX_INSTANCE_NODES = 100000
};
static const int vFREE_CLASS_BLOCK_ID = 0x02030405;
static const int vFREE_INST_BLOCK_ID = 0x27354351;
/*****************************************************************************
** Private Types **
*****************************************************************************/
struct FreeNode
{
FreeNode* next;
int id;
} ;
union ClassNodeBlock
{
char pad[sizeof(Spt::ClassNode)];
FreeNode free_node;
};
union InstanceNodeBlock
{
char pad[sizeof(Spt::ClassNode::InstanceNode)];
FreeNode free_node;
};
/*****************************************************************************
** Private Data **
*****************************************************************************/
static ClassNodeBlock* spClassNodeFreeList = NULL;
static InstanceNodeBlock* spInstanceNodeFreeList = NULL;
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
void set_up( void )
{
spClassNodeFreeList = (ClassNodeBlock*)_dbg_start;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
for( int i = 0; i < ( vMAX_CLASS_NODES - 1 ); i++ )
{
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
p_class_node->free_node.next = (FreeNode*)(++p_class_node);
}
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
for( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )
{
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
p_inst_node->free_node.next = (FreeNode*)(++p_inst_node);
}
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;
Dbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end,
"Dbg Mem Block not big enough (%d bytes too small)", (int)p_inst_node - (int)_dbg_end );
if ( (int)p_inst_node < ((int)_dbg_end))
{
Dbg_Warning ( "%dbytes unused in Dbg mem block",((int)_dbg_end - (int)p_inst_node));
}
Dbg_Notify ( "Dbg Mem Block Allocated successfully" );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
int count = 0;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
do
{
Dbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, "Block not free" );
p_class_node = (ClassNodeBlock*)p_class_node->free_node.next;
count++;
} while ( p_class_node != spClassNodeFreeList );
Dbg_MsgAssert ( count == vMAX_CLASS_NODES,
"%d Class Nodes still registered", vMAX_CLASS_NODES - count );
count = 0;
do
{
Dbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, "Block not free" );
p_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;
count++;
} while ( p_inst_node != spInstanceNodeFreeList );
Dbg_MsgAssert ( count == vMAX_INSTANCE_NODES,
"%d Instance Nodes still registered", vMAX_INSTANCE_NODES - count );
Dbg_Notify ( "Dbg Mem Block Released successfully" );
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
void* NewClassNode( size_t size )
{
void* p_ret = (void*)spClassNodeFreeList;
Dbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next),
"ClassNode pool full" );
Dbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, "Not a Free Class Node" );
spClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;
// printf("NewClassNode %p next %p\n",p_ret, spClassNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteClassNode( void* pMem )
{
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
ClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;
spClassNodeFreeList = (ClassNodeBlock*)p_freeblock;
spClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;
// printf("DeleteClassNode %p next %p\n",spClassNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* NewInstanceNode( size_t size )
{
void* p_ret = (void*)spInstanceNodeFreeList;
Dbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next),
"InstanceNode pool full" );
Dbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, "Not a Free Instance Node" );
spInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;
// printf("NewInstanceNode %p next %p\n",p_ret, spInstanceNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteInstanceNode( void* pMem )
{
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
InstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;
spInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;
// printf("DeleteInstanceNode %p next %p\n",spInstanceNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#else // __NOPT_FULL_DEBUG__
void set_up( void )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
}
#endif // __NOPT_FULL_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Dbg
#endif // __NOPT_DEBUG__
#ifdef __NOPT_ASSERT__
namespace Dbg
{
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_print( char *text )
{
std::printf( text );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_trap( char* mess )
{
uint* ptr = reinterpret_cast< uint* >( 0x00000001 );
*ptr = 0;
}
} // namespace Dbg
#endif

159
Code/Core/Debug/Project.h Normal file
View File

@ -0,0 +1,159 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Confidential Information **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (Dbg_) **
** **
** File name: core/debug/project.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_PROJECT_H
#define __CORE_DEBUG_PROJECT_H
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
#include "mem_stat.h"
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Type Defines **
*****************************************************************************/
namespace Dbg
{
class Project
{
public :
Project ( const char& name, const char& description );
void SetChildren ( Dbg::Module* children );
Dbg::Module* GetChildren ( void ) const;
private :
const char& name;
const char& description;
Project* next; // pointer to next registered project
Dbg::Module* children; // pointer to children modules
Dbg_MEMORY_STATS stats;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
extern Dbg::Project* RegisteredProjects;
} // namespace Dbg
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
#define Dbg_DefineProject(proj,des) \
\
Dbg::Project& Dbg_project_##proj ( void ) \
{ \
static Dbg::Project project ( *#proj, *des ); \
\
return project; \
}
\
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
namespace Dbg
{
inline Project::Project ( const char& name, const char& description )
: name ( name ), description ( description )
{
next = RegisteredProjects;
RegisteredProjects = this;
children = NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Project::SetChildren ( Dbg::Module* children_in )
{
children = children_in;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Dbg::Module* Project::GetChildren ( void ) const
{
return children;
}
} // namespace Dbg
/*****************************************************************************
** Stubs **
*****************************************************************************/
#else
#define Dbg_DefineProject(proj,des)
#endif //__NOPT_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_DEBUG_PROJECT_H

124
Code/Core/Debug/Signatrs.h Normal file
View File

@ -0,0 +1,124 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (Dbg_) **
** **
** File name: core/debug/signatrs.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_DEBUG_SIGNATRS_H
#define __CORE_DEBUG_SIGNATRS_H
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Type Defines **
*****************************************************************************/
class Module;
class Signature
{
public :
Signature( char* name, const Module& module );
Signature( const char* cl, char* name, const Module& module );
const char& GetName( void ) const ;
private :
char* m_name; // function's name
const Module& m_module; // function's module
};
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline Signature::Signature( char* name, const Module& module )
: m_name ( name ),
m_module ( module )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline const char& Signature::GetName( void ) const
{
return *m_name;
}
} // namespace Dbg
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
#ifdef __PLAT_NGC__
extern Dbg::Module& Dbg_module;
extern Dbg::Signature Dbg_signature;
#endif
#ifndef __NOPT_STRICT_SIGNATURES__
extern Dbg::Module& Dbg_module;
extern Dbg::Signature Dbg_signature;
#endif
#endif // __NOPT_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_DEBUG_SIGNATRS_H

View File

@ -0,0 +1,155 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: p_debug.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Platform specific debug code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <core/defines.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
#ifdef __NOPT_DEBUG__
void set_up ( void )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down ( void )
{
}
#endif // __NOPT_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_print ( char *text )
{
#ifdef __PLAT_WN32__
OutputDebugString ( text );
#else
printf ( text );
#endif // __CC_VISUALC__
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_trap ( char* message )
{
#ifdef __CC_VISUALC__
#ifdef __ALLOW_CONTINUE__
switch ( MessageBox ( GetActiveWindow(), message, "Assertion Failure - Trigger Debugger ?",
MB_DEFBUTTON1 | MB_YESNO | MB_ICONEXCLAMATION ))
{
case IDYES:
__asm int 3; // trigger the debugger
break;
}
#else // __ALLOW_CONTINUE__
MessageBox ( GetActiveWindow(), message, "Assertion Failure",
MB_DEFBUTTON1 | MB_ICONEXCLAMATION );
__asm int 3;
#endif // __ALLOW_CONTINUE__
#else // __CC_VISUALC__
exit(-10);
#endif // __CC_VISUALC__
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
}

View File

@ -0,0 +1,341 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: p_debug.cpp **
** **
** Created by: 09/25/00 - dc **
** **
** Description: Platform specific debug code **
** **
*****************************************************************************/
#include <xtl.h>
#include <core/defines.h>
#include <core/support.h>
#include <core/debug.h>
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Externals **
*****************************************************************************/
extern char _dbg_start[];
extern char _dbg_end[];
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Dbg
{
Dbg_Module // module this code belongs to
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __NOPT_FULL_DEBUG__
enum
{
vMAX_CLASS_NODES = 28000,
vMAX_INSTANCE_NODES = 100000
};
static const int vFREE_CLASS_BLOCK_ID = 0x02030405;
static const int vFREE_INST_BLOCK_ID = 0x27354351;
/*****************************************************************************
** Private Types **
*****************************************************************************/
struct FreeNode
{
FreeNode* next;
int id;
} ;
union ClassNodeBlock
{
char pad[sizeof(Spt::ClassNode)];
FreeNode free_node;
};
union InstanceNodeBlock
{
char pad[sizeof(Spt::ClassNode::InstanceNode)];
FreeNode free_node;
};
/*****************************************************************************
** Private Data **
*****************************************************************************/
static ClassNodeBlock* spClassNodeFreeList = NULL;
static InstanceNodeBlock* spInstanceNodeFreeList = NULL;
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
void set_up( void )
{
Dbg_Function;
spClassNodeFreeList = (ClassNodeBlock*)_dbg_start;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
for( int i = 0; i < ( vMAX_CLASS_NODES - 1 ); i++ )
{
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
p_class_node->free_node.next = (FreeNode*)(++p_class_node);
}
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
for( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )
{
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
p_inst_node->free_node.next = (FreeNode*)(++p_inst_node);
}
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;
Dbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end,
"Dbg Mem Block not big enough (%d bytes too small)", (int)p_inst_node - (int)_dbg_end );
if ( (int)p_inst_node < ((int)_dbg_end))
{
Dbg_Warning ( "%dbytes unused in Dbg mem block",((int)_dbg_end - (int)p_inst_node));
}
Dbg_Notify ( "Dbg Mem Block Allocated successfully" );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
Dbg_Function;
int count = 0;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
do
{
Dbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, "Block not free" );
p_class_node = (ClassNodeBlock*)p_class_node->free_node.next;
count++;
} while ( p_class_node != spClassNodeFreeList );
Dbg_MsgAssert ( count == vMAX_CLASS_NODES,
"%d Class Nodes still registered", vMAX_CLASS_NODES - count );
count = 0;
do
{
Dbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, "Block not free" );
p_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;
count++;
} while ( p_inst_node != spInstanceNodeFreeList );
Dbg_MsgAssert ( count == vMAX_INSTANCE_NODES,
"%d Instance Nodes still registered", vMAX_INSTANCE_NODES - count );
Dbg_Notify ( "Dbg Mem Block Released successfully" );
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
void* NewClassNode( size_t size )
{
Dbg_Function;
void* p_ret = (void*)spClassNodeFreeList;
Dbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next),
"ClassNode pool full" );
Dbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, "Not a Free Class Node" );
spClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;
// printf("NewClassNode %p next %p\n",p_ret, spClassNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteClassNode( void* pMem )
{
Dbg_Function;
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
ClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;
spClassNodeFreeList = (ClassNodeBlock*)p_freeblock;
spClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;
// printf("DeleteClassNode %p next %p\n",spClassNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* NewInstanceNode( size_t size )
{
Dbg_Function;
void* p_ret = (void*)spInstanceNodeFreeList;
Dbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next),
"InstanceNode pool full" );
Dbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, "Not a Free Instance Node" );
spInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;
// printf("NewInstanceNode %p next %p\n",p_ret, spInstanceNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteInstanceNode( void* pMem )
{
Dbg_Function;
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
InstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;
spInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;
// printf("DeleteInstanceNode %p next %p\n",spInstanceNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#else // __NOPT_FULL_DEBUG__
void set_up( void )
{
Dbg_Function;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
Dbg_Function;
}
#endif // __NOPT_FULL_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Dbg
#endif // __NOPT_DEBUG__
#ifdef __NOPT_ASSERT__
namespace Dbg
{
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_print( char *text )
{
OutputDebugString( text );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_trap( char* message )
{
OutputDebugString( message );
uint* ptr = reinterpret_cast< uint* >( 0x00000001 );
*ptr = NULL;
}
} // namespace Dbg
#endif

205
Code/Core/Debug/log.cpp Normal file
View File

@ -0,0 +1,205 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: log.cpp **
** **
** Created by: 09/25/02 - ksh **
** **
** Description: Logging code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <stdio.h>
#include <core/defines.h>
#include <core/support.h>
#include <core/debug.h>
#include <sys/config/config.h>
#ifndef __PLAT_WN32__
#include <gfx/gfxman.h>
#endif // __PLAT_WN32__
#ifdef __PLAT_NGC__
#include <dolphin.h>
#define _output OSReport
#else
#define _output printf
#endif
#ifdef __NOPT_ASSERT__
#ifdef __PLAT_NGPS__
/*****************************************************************************
** DBG Information **
*****************************************************************************/
// 128 bytes each (sizeof(SLogEntry)) and they come off the debug heap.
#define MAX_LOG_ENTRIES 20000
extern char _log_info_start[];
extern char _log_info_end[];
namespace Log
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
// Chosen just to make sizeof(SLogEntry) a nice round 128
#define MAX_MESSAGE_LENGTH 107
struct SLogEntry
{
Tmr::CPUCycles mCPUTime;
const char *mpSourceFileName;
const char *mpFunctionName;
int mLineNumber;
char mpMessage[MAX_MESSAGE_LENGTH+1];
};
//char p_foo[sizeof(SLogEntry)/0];
struct SLogBufferInfo
{
// Pointer to the start of the big log buffer, which will be in the debug heap somewhere.
SLogEntry *mpBuffer;
// The total number of entries in the buffer.
int mTotalEntries;
// The number of entries written to so far. This starts at 0 when the game starts,
// and increases till it hits mTotalEntries, then stays at that value.
int mNumEntries;
// Points to just after the last entry that got added to the buffer.
// So it may not point to a valid SLogEntry, for example when the buffer is filling
// up, or when pTop points to the end of pBuffer.
SLogEntry *mpTop;
};
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
static bool sInitialised=false;
static SLogBufferInfo *spLogInfo=NULL;
static SLogEntry *spNotALeak=NULL;
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
void Init()
{
if (Config::GotExtraMemory())
{
Dbg_MsgAssert(!sInitialised,("Tried to call Log::Init twice"));
Dbg_MsgAssert((uint32)(_log_info_end-_log_info_start) >= sizeof(SLogBufferInfo),("log_info section too small, got=%d, required=%d",(uint32)(_log_info_end-_log_info_start),sizeof(SLogBufferInfo)));
spLogInfo=(SLogBufferInfo*)_log_info_start;
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().DebugHeap());
spLogInfo->mNumEntries=0;
spLogInfo->mTotalEntries=MAX_LOG_ENTRIES;
spLogInfo->mpBuffer=(SLogEntry*)Mem::Malloc(MAX_LOG_ENTRIES*sizeof(SLogEntry));
spNotALeak=spLogInfo->mpBuffer;
spLogInfo->mpTop=spLogInfo->mpBuffer;
uint32 *p_long=(uint32*)spLogInfo->mpBuffer;
Dbg_MsgAssert((sizeof(SLogEntry)&3)==0,("sizeof(SLogEntry) not a multiple of 4"));
for (uint32 i=0; i<MAX_LOG_ENTRIES*sizeof(SLogEntry)/4; ++i)
{
*p_long++=0;
}
Mem::Manager::sHandle().PopContext();
sInitialised=true;
}
}
void AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message)
{
if (Config::GotExtraMemory())
{
Dbg_MsgAssert(sInitialised,("Log::AddEntry called before Log::Init called"));
SLogEntry *p_new=NULL;
if (spLogInfo->mNumEntries < MAX_LOG_ENTRIES)
{
p_new=spLogInfo->mpTop++;
++spLogInfo->mNumEntries;
}
else
{
if (spLogInfo->mpTop >= spLogInfo->mpBuffer+MAX_LOG_ENTRIES)
{
spLogInfo->mpTop=spLogInfo->mpBuffer;
}
p_new=spLogInfo->mpTop++;
}
p_new->mCPUTime=Tmr::GetTimeInCPUCycles();
p_new->mLineNumber=lineNumber;
p_new->mpFunctionName=p_functionName;
p_new->mpSourceFileName=p_fileName;
if (p_message)
{
Dbg_MsgAssert(strlen(p_message)<=MAX_MESSAGE_LENGTH,("Log message '%s' too long",p_message));
strcpy(p_new->mpMessage,p_message);
}
else
{
p_new->mpMessage[0]=0;
}
}
}
} // namespace Log
#else
namespace Log
{
void Init()
{
}
void AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message)
{
}
} // namespace Log
#endif // #ifdef __PLAT_NGPS__
#endif //__NOPT_ASSERT__

View File

@ -0,0 +1,328 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Debug (DBG) **
** **
** File name: p_debug.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Platform specific debug code **
** **
*****************************************************************************/
#include <stdio.h>
#include <core/defines.h>
#include <core/support.h>
#include <core/debug.h>
#include <libsn.h>
#ifdef __NOPT_DEBUG__
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Externals **
*****************************************************************************/
extern char _dbg_start[];
extern char _dbg_end[];
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Dbg
{
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __NOPT_FULL_DEBUG__
enum
{
vMAX_CLASS_NODES = 28000,
vMAX_INSTANCE_NODES = 100000
};
static const int vFREE_CLASS_BLOCK_ID = 0x02030405;
static const int vFREE_INST_BLOCK_ID = 0x27354351;
/*****************************************************************************
** Private Types **
*****************************************************************************/
struct FreeNode
{
FreeNode* next;
int id;
} ;
union ClassNodeBlock
{
char pad[sizeof(Spt::ClassNode)];
FreeNode free_node;
};
union InstanceNodeBlock
{
char pad[sizeof(Spt::ClassNode::InstanceNode)];
FreeNode free_node;
};
/*****************************************************************************
** Private Data **
*****************************************************************************/
static ClassNodeBlock* spClassNodeFreeList = NULL;
static InstanceNodeBlock* spInstanceNodeFreeList = NULL;
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
void set_up( void )
{
spClassNodeFreeList = (ClassNodeBlock*)_dbg_start;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
for( int i = 0; i < ( vMAX_CLASS_NODES - 1 ); i++ )
{
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
p_class_node->free_node.next = (FreeNode*)(++p_class_node);
}
p_class_node->free_node.id = vFREE_CLASS_BLOCK_ID;
(p_class_node++)->free_node.next = (FreeNode*)spClassNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)(++p_class_node);
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
for( int i = 0; i < ( vMAX_INSTANCE_NODES - 1 ) ; i++ )
{
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
p_inst_node->free_node.next = (FreeNode*)(++p_inst_node);
}
p_inst_node->free_node.id = vFREE_INST_BLOCK_ID;
(p_inst_node++)->free_node.next = (FreeNode*)spInstanceNodeFreeList;
Dbg_MsgAssert( (int)p_inst_node <= (int)_dbg_end,
"Dbg Mem Block not big enough (%d bytes too small)", (int)p_inst_node - (int)_dbg_end );
if ( (int)p_inst_node < ((int)_dbg_end))
{
Dbg_Warning ( "%dbytes unused in Dbg mem block",((int)_dbg_end - (int)p_inst_node));
}
Dbg_Notify ( "Dbg Mem Block Allocated successfully" );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
int count = 0;
ClassNodeBlock* p_class_node = spClassNodeFreeList;
InstanceNodeBlock* p_inst_node = spInstanceNodeFreeList;
do
{
Dbg_MsgAssert ( p_class_node->free_node.id == vFREE_CLASS_BLOCK_ID, "Block not free" );
p_class_node = (ClassNodeBlock*)p_class_node->free_node.next;
count++;
} while ( p_class_node != spClassNodeFreeList );
Dbg_MsgAssert ( count == vMAX_CLASS_NODES,
"%d Class Nodes still registered", vMAX_CLASS_NODES - count );
count = 0;
do
{
Dbg_MsgAssert ( p_inst_node->free_node.id == vFREE_INST_BLOCK_ID, "Block not free" );
p_inst_node = (InstanceNodeBlock*)p_inst_node->free_node.next;
count++;
} while ( p_inst_node != spInstanceNodeFreeList );
Dbg_MsgAssert ( count == vMAX_INSTANCE_NODES,
"%d Instance Nodes still registered", vMAX_INSTANCE_NODES - count );
Dbg_Notify ( "Dbg Mem Block Released successfully" );
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
void* NewClassNode( size_t size )
{
void* p_ret = (void*)spClassNodeFreeList;
Dbg_MsgAssert ( (int)spClassNodeFreeList != (int)(spClassNodeFreeList->free_node.next),
"ClassNode pool full" );
Dbg_MsgAssert ( spClassNodeFreeList->free_node.id == vFREE_CLASS_BLOCK_ID, "Not a Free Class Node" );
spClassNodeFreeList = (ClassNodeBlock*)spClassNodeFreeList->free_node.next;
// printf("NewClassNode %p next %p\n",p_ret, spClassNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteClassNode( void* pMem )
{
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
ClassNodeBlock* p_freeblock = (ClassNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spClassNodeFreeList;
spClassNodeFreeList = (ClassNodeBlock*)p_freeblock;
spClassNodeFreeList->free_node.id = vFREE_CLASS_BLOCK_ID;
// printf("DeleteClassNode %p next %p\n",spClassNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* NewInstanceNode( size_t size )
{
void* p_ret = (void*)spInstanceNodeFreeList;
Dbg_MsgAssert ( (int)spInstanceNodeFreeList != (int)(spInstanceNodeFreeList->free_node.next),
"InstanceNode pool full" );
Dbg_MsgAssert ( spInstanceNodeFreeList->free_node.id == vFREE_INST_BLOCK_ID, "Not a Free Instance Node" );
spInstanceNodeFreeList = (InstanceNodeBlock*)spInstanceNodeFreeList->free_node.next;
// printf("NewInstanceNode %p next %p\n",p_ret, spInstanceNodeFreeList);
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void DeleteInstanceNode( void* pMem )
{
Dbg_MsgAssert ( (((int)pMem >= (int)_dbg_start ) && (((int)pMem < (int)_dbg_end ))),
"Memory not in Debug block (%p)",pMem );
InstanceNodeBlock* p_freeblock = (InstanceNodeBlock*)pMem;
p_freeblock->free_node.next = (FreeNode*)spInstanceNodeFreeList;
spInstanceNodeFreeList = (InstanceNodeBlock*)p_freeblock;
spInstanceNodeFreeList->free_node.id = vFREE_INST_BLOCK_ID;
// printf("DeleteInstanceNode %p next %p\n",spInstanceNodeFreeList, p_freeblock->free_node.next);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#else // __NOPT_FULL_DEBUG__
void set_up( void )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void close_down( void )
{
}
#endif // __NOPT_FULL_DEBUG__
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Dbg
#endif // __NOPT_DEBUG__
#ifdef __NOPT_ASSERT__
namespace Dbg
{
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_print( char *text )
{
std::printf( text );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void default_trap( char* message )
{
// uint* ptr = reinterpret_cast< uint* >( 0x00000001 );
//
// *ptr = NULL;
snPause();
}
} // namespace Dbg
#endif

559
Code/Core/Defines.h Normal file
View File

@ -0,0 +1,559 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Standard Header **
** **
** File name: core/defines.h **
** **
** Created: 05/27/99 - mjb **
** **
** All code depends on the definitions in this files **
** It should be included in every file **
** **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#define __CORE_DEFINES_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifdef __PLAT_WN32__
//#include <strstream>
//#include <fstream.h>
#ifdef __USE_OLD_STREAMS__
#include <iostream.h>
#else
#include <iostream>
using namespace std;
#endif
#include <stdio.h>
#include <string.h>
#pragma warning( disable : 4800 )
#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
#pragma warning( disable : 4291 ) // no matching operator delete found
#else
#ifdef __PLAT_NGPS__
#include <stdio.h>
#include <eetypes.h>
//#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#else
#ifdef __PLAT_NGC__
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <typeinfo>
#else
#ifdef __PLAT_XBOX__
#include <stdio.h>
//#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#pragma warning( disable : 4800 )
#pragma warning( disable : 4291 ) // no matching operator delete found
#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
#pragma warning( disable : 4995 ) // name was marked as #pragma deprecated
#endif
#endif
#endif
#endif
#ifndef __PLAT_WN32__
//#ifdef __NOPT_ASSERT__
#ifdef __PLAT_NGC__
#ifdef __NOPT_FINAL__
#define printf(A...)
#else
int OurPrintf(const char *fmt, ...);
#define printf OurPrintf
#endif
#else
int OurPrintf(const char *fmt, ...);
#define printf OurPrintf
#endif
//#else
// inline void NullPrintf(const char *fmt, ...){}
// #define printf NullPrintf
//#endif
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
#define vINT8_MAX 0x7F
#define vINT8_MIN 0x81
#define vINT16_MAX 0x7FFF
#define vINT16_MIN 0x8001
#define vINT32_MAX 0x7FFFFFFF
#define vINT32_MIN 0x80000001
#define vINT64_MAX 0x7FFFFFFFFFFFFFFF
#define vINT64_MIN 0x8000000000000001
#define vUINT8_MAX 0xFF
#define vUINT16_MAX 0xFFFF
#define vUINT32_MAX 0xFFFFFFFF
#define vUINT64_MAX 0xFFFFFFFFFFFFFFFF
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
#ifndef NULL
#define NULL 0
#endif
/*****************************************************************************
** Type Defines **
*****************************************************************************/
typedef char int8;
typedef short int16;
typedef unsigned int uint;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef signed int sint;
typedef signed char sint8;
typedef signed short sint16;
#define vINT_MAX vINT32_MAX
#define vINT_MIN vINT32_MIN
#define vUINT_MAX vUINT32_MAX
#ifdef __PLAT_WN32__
typedef long int32;
typedef unsigned long uint32;
typedef signed long sint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
typedef signed __int64 sint64;
#endif
#ifdef __PLAT_NGPS__
typedef int int32;
typedef unsigned int uint32;
typedef signed int sint32;
typedef long int64;
typedef unsigned long uint64;
typedef signed long sint64;
typedef long128 int128;
typedef u_long128 uint128;
typedef long128 sint128;
#endif
#ifdef __PLAT_XBOX__
typedef long int32;
typedef unsigned long uint32;
typedef signed long sint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
typedef signed __int64 sint64;
#endif
#ifdef __PLAT_NGC__
typedef int int32;
typedef unsigned int uint32;
typedef signed int sint32;
typedef long long int64;
typedef unsigned long long uint64;
typedef signed long long sint64;
// Paul: No GameCube 128-bit types.
//typedef long128 int128;
//typedef u_long128 uint128;
//typedef long128 sint128;
typedef long long int128;
typedef unsigned long long uint128;
typedef signed long long sint128;
#endif
#if defined(__PLAT_NGPS__) || defined(__PLAT_XBOX__) || defined(__PLAT_NGC__)
class ostream
{
public:
ostream& operator<< ( char* str ) { printf ( str ); return *this; }
ostream& operator<< ( const char* str ) { printf ( str ); return *this; }
ostream& operator<< ( sint i ) { printf ( "%d", i ); return *this; }
ostream& operator<< ( uint i ) { printf ( "%u", i ); return *this; }
ostream& operator<< ( float f ) { printf ( "%f", f ); return *this; }
ostream& operator<< ( void* p ) { printf ( "%p", p ); return *this; }
ostream& operator<< ( const void* p ) { printf ( "%p", p ); return *this; }
};
#endif
#define vINT_BITS 32
#define vPTR_BITS 32
/******************************************************************/
/* */
/* */
/******************************************************************/
// Alignment macros
#ifdef __PLAT_NGPS__
#define nAlign(bits) __attribute__((aligned((bits>>3))))
#else
#define nAlign(bits)
#endif
#define nPad64(X) uint64 _pad##X;
#define nPad32(X) uint32 _pad##X;
#define nPad16(X) uint16 _pad##X;
#define nPad8(X) uint8 _pad##X;
/******************************************************************/
/* */
/* */
/******************************************************************/
// version stamping
#define __nTIME__ __TIME__
#define __nDATE__ __DATE__
/******************************************************************/
/* */
/* */
/******************************************************************/
#define nBit(b) ( 1 << (b) )
typedef sint nID;
typedef sint8 nID8;
typedef sint16 nID16;
typedef sint32 nID32;
typedef sint64 nID64;
#define nMakeID(a,b,c,d) ( (nID) ( ( (nID) (a) ) << 24 | ( (nID) (b) ) << 16 | \
( (nID) (c) ) << 8 | ( (nID) (d) ) ) )
// nMakeStructID() differs from nMakeID in that struct IDs are always
// readable from a memory dump, where as IDs would be reversed on little
// endian machines
#if __CPU_BIG_ENDIAN__
#define nMakeStructID(a,b,c,d) ( (nID) ( ((nID)(a))<<24 | ((nID)(b))<<16 | \
((nID)(c))<<8 | ((nID)(d)) ))
#else
#define nMakeStructID(a,b,c,d) ( (ID) ( ((nID)(d))<<24 | ((nID)(c))<<16 | \
((nID)(b))<<8 | ((nID)(a)) ))
#endif
/*****************************************************************************
** Macros **
*****************************************************************************/
#define nReverse32(L) ( (( (L)>>24 ) & 0xff) | (((L)>>8) &0xff00) | (((L)<<8)&0xff0000) | (((L)<<24)&0xff000000))
#define nReverse16(L) ( (( (L)>>8 ) & 0xff) | (((L)<<8)&0xff00) )
#if __CPU_BIG_ENDIAN__
#define nBgEn32(L) (L)
#define nBgEn16(L) (L)
#define nLtEn32(L) nReverse32(L)
#define nLtEn16(L) nReverse16(L)
#else
#define nBgEn32(L) nReverse32(L)
#define nBgEn16(L) nReverse16(L)
#define nLtEn32(L) (L)
#define nLtEn16(L) (L)
#endif
#ifdef __PLAT_XBOX__
#define __PRETTY_FUNCTION__ "?"
#define isnanf _isnan
#define isinff _isnan
#endif
/******************************************************************/
/* */
/* */
/******************************************************************/
#define __CPU_WORD_BALIGN__ 4 // Memory word byte alignment
#define PTR_ALIGNMASK ( vUINT_MAX << __CPU_WORD_BALIGN__)
// The alignment macros align elements for fastest access
#define nAligned(P) ( !( (uint) (P) & (~PTR_ALIGNMASK) ) )
#define nAlignDown(P) (void*)( (uint) (P) & PTR_ALIGNMASK )
#define nAlignUp(P) (void*)( ( (uint) (P) + ( 1 << __CPU_WORD_BALIGN__ ) - 1 ) & PTR_ALIGNMASK )
#define nAlignedBy(P,A) ( !( (uint) (P) & ( ~(vUINT_MAX << (A) ) ) ) )
#define nAlignDownBy(P,A) (void*)( (uint) (P) & (vUINT_MAX << (A) ) )
#define nAlignUpBy(P,A) (void*)( ( (uint) (P) + ( 1 << (A) ) - 1 ) & ( vUINT_MAX <<( A ) ) )
#define nStorage(X) nAlignUp ( (X) + 1 )
/****************************************************************************/
#define nAddPointer(P,X) (void*) ( (uint) (P) + (uint) (X) )
#define nSubPointer(P,X) (void*) ( (uint) (P) - (uint) (X) )
/****************************************************************************/
// Converts a string into a checksum. This macro can be used for readability.
// Later, for speed, some application can scan all .cpp and .h files, and
// replace all instances of CRCX(...) with corresponding CRCD(...) instances
//
// Example: CRCX("object_id")
#define CRCX(_s) Script::GenerateCRC(_s)
// This macro exists simply for readability. Whenever you see a CRCD(...) instance,
// you will know what string the checksum maps to. CRCD(...) instances in the code
// can be generated from CRCX(...), and can be reverse mapped if desired.
//
// Example: CRCD(0xdcd2a9d4, "object_id")
#include <core/debug.h>
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/support.h>
#include <sys/mem/memman.h>
#include <core/crc.h>
#ifdef __PLAT_NGPS__
#include <gfx/ngps/p_memview.h>
#include "libsn.h"
#elif defined( __PLAT_NGC__ )
#include <gfx/ngc/p_memview.h>
//#include "libsn.h"
#elif defined( __PLAT_XBOX__ )
#include <gfx/xbox/p_memview.h>
#endif
// Mick: This check slows the game down quite a bit
#if 1 && defined( __NOPT_ASSERT__ )
extern uint32 check_checksum(uint32 _i, const char *_s, const char *f, int line);
#define CRCD(_i, _s) check_checksum(_i, _s, __FILE__, __LINE__)
#else
#define CRCD(_i, _s) _i
#endif
// CRC-C, for use only in switch statements, where you want to use the same syntax as CRCD
#define CRCC(_i, _s) _i
//#ifdef __PLAT_NGC__
//class TCPPInit
//{
//public:
// static bool IsHeapInitialized ;
//} ;
//
//// these definitions override the new and delete operators.
//
#ifdef __PLAT_NGC__
static inline void* operator new ( size_t blocksize ) ;
static inline void* operator new[] ( size_t blocksize ) ;
static inline void operator delete ( void* block ) ;
static inline void operator delete[] ( void* block ) ;
#endif // __PLAT_NGC__
//
//#else
#ifdef __PLAT_WN32__
inline void* operator new( size_t size, bool assert_on_fail )
{
return new char[size];
}
#else
#ifndef __PLAT_NGC__
/******************************************************************/
/* Global new/delete operators */
/* */
/******************************************************************/
inline void* operator new( size_t size )
{
return Mem::Manager::sHandle().New( size, true );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new[] ( size_t size )
{
return Mem::Manager::sHandle().New( size, true );
}
#endif // __PLAT_NGC__
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new( size_t size, bool assert_on_fail )
{
return Mem::Manager::sHandle().New( size, assert_on_fail );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new[] ( size_t size, bool assert_on_fail )
{
return Mem::Manager::sHandle().New( size, assert_on_fail );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true )
{
return Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true )
{
return Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new( size_t size, void* pLocation )
{
return pLocation;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void* operator new[]( size_t size, void* pLocation )
{
return pLocation;
}
#ifndef __PLAT_NGC__
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void operator delete( void* pAddr )
{
Mem::Manager::sHandle().Delete( pAddr );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void operator delete[]( void* pAddr )
{
Mem::Manager::sHandle().Delete( pAddr );
}
#endif // __PLAT_NGC__
//#ifdef __PLAT_NGC__
/******************************************************************/
/* only used when exception is thrown in constructor */
/* */
/******************************************************************
inline void operator delete( void* pAddr, Mem::Allocator* pAlloc )
{
Mem::Manager * mem_man = Mem::Manager::Instance();
Mem::Manager::sHandle().Delete( pAddr );
}
/******************************************************************/
/* */
/* */
/******************************************************************
inline void operator delete[]( void* pAddr, Mem::Allocator* pAlloc )
{
Mem::Manager * mem_man = Mem::Manager::Instance();
Mem::Manager::sHandle().Delete( pAddr );
}
/******************************************************************/
/* */
/* */
/******************************************************************
inline void operator delete( void*, void* pLocation )
{
return;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
//#endif // __PLAT_NGC__
#endif // __PLAT_WN32__
#endif // __CORE_DEFINES_H

View File

@ -0,0 +1,87 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: List **
** **
** File name: **
** **
** Created by: **
** **
** Description: **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/DynamicTable.h>
//
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************************
*
* Function:
*
* Description: Default constructor
*
* Parameters:
*
*****************************************************************************/
} // namespace Lst

274
Code/Core/DynamicTable.h Normal file
View File

@ -0,0 +1,274 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: DynamicTable **
** **
** File name: Core\DynamicTable.h **
** **
** Created by: 12/14/2000 - rjm **
** **
** Description: A handy DynamicTable class **
** **
*****************************************************************************/
#ifndef __CORE_LIST_DYNAMICTABLE_H
#define __CORE_LIST_DYNAMICTABLE_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
nTemplateBaseClass(_V, DynamicTable)
{
Dbg_TemplateBaseClass(_V, DynamicTable);
public:
DynamicTable(int size, int grow_increment = 8);
~DynamicTable();
// it goes on the end of the table
void Add(_V *pItem);
int GetSize();
void Reset();
_V &Last();
void Replace(int index, _V *pNewItem);
void Remove(int index);
/*
bool IsEmpty(int index);
*/
_V &operator[](int index);
private:
_V ** mpp_table;
int m_size;
int m_entriesFilled;
int m_growIncrement;
};
template<class _V>
class DynamicTableDestroyer
{
public:
DynamicTableDestroyer(DynamicTable<_V> *pTable);
void DeleteTableContents();
private:
DynamicTable<_V> * mp_table;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
template<class _V>
DynamicTable<_V>::DynamicTable(int size, int grow_increment)
{
m_size = size;
m_growIncrement = grow_increment;
mpp_table = (_V**) Mem::Malloc(sizeof(_V *) * m_size);
//mpp_table = new _V*[m_size];
for (int i = 0; i < m_size; i++)
mpp_table[i] = NULL;
m_entriesFilled = 0;
}
template<class _V>
DynamicTable<_V>::~DynamicTable()
{
Mem::Free(mpp_table);
//delete [] mpp_table;
}
template<class _V>
void DynamicTable<_V>::Add(_V* pItem)
{
Dbg_MsgAssert(pItem,( "can't add NULL item to table"));
// do we need to create a new table?
if (m_size <= m_entriesFilled)
{
// create new table
int new_size = m_size + m_growIncrement;
_V **ppTemp = (_V**) Mem::Malloc(sizeof(_V *) * new_size);
//_V **ppTemp = new _V*[new_size];
// copy contents of old one
int i;
for (i = 0; i < m_size; i++)
ppTemp[i] = mpp_table[i];
for (i = m_size; i < new_size; i++)
ppTemp[i] = NULL;
Mem::Free(mpp_table);
//delete [] mpp_table;
mpp_table = ppTemp;
m_size = new_size;
}
mpp_table[m_entriesFilled++] = pItem;
}
template<class _V>
int DynamicTable<_V>::GetSize()
{
return m_entriesFilled;
}
template<class _V>
void DynamicTable<_V>::Reset()
{
m_entriesFilled = 0;
}
template<class _V>
void DynamicTable<_V>::Replace(int index, _V *pNewItem)
{
Dbg_MsgAssert(index >= 0 && index < m_entriesFilled,( "index out of bounds in DynamicTable"));
Dbg_AssertPtr(pNewItem);
mpp_table[index] = pNewItem;
}
template<class _V>
void DynamicTable<_V>::Remove(int index)
{
Dbg_MsgAssert(index >= 0 && index < m_entriesFilled,( "index out of bounds in DynamicTable"));
delete mpp_table[index];
for ( int i = index; i < m_entriesFilled-1; i++ )
{
mpp_table[i] = mpp_table[i+1];
}
mpp_table[m_entriesFilled-1] = NULL;
m_entriesFilled--;
}
/*
template<class _V>
bool DynamicTable<_V>::IsEmpty(int index)
{
Dbg_MsgAssert(index >= 0 && index < m_entriesFilled,( "index out of bounds in DynamicTable"));
if (mpp_table[index]) return false;
return true;
}
*/
template<class _V>
_V &DynamicTable<_V>::operator[](int index)
{
Dbg_MsgAssert(index >= 0 && index < m_entriesFilled,( "index %d out of bounds in DynamicTable", index));
Dbg_MsgAssert(mpp_table[index],( "table entry is NULL"));
Dbg_AssertPtr(mpp_table[index]);
return *mpp_table[index];
}
template<class _V>
_V &DynamicTable<_V>::Last()
{
Dbg_MsgAssert(m_entriesFilled > 0,( "empty list"));
return *mpp_table[m_entriesFilled-1];
}
template<class _V>
DynamicTableDestroyer<_V>::DynamicTableDestroyer(DynamicTable<_V> *pTable)
{
mp_table = pTable;
}
template<class _V>
void DynamicTableDestroyer<_V>::DeleteTableContents()
{
int size = mp_table->GetSize();
for (int i = 0; i < size; i++)
{
//if (!mp_table->IsEmpty())
delete &(*mp_table)[i];
}
mp_table->Reset();
}
} // namespace Lst
#endif // __CORE_LIST_DYNAMICTABLE_H

515
Code/Core/HashTable.h Normal file
View File

@ -0,0 +1,515 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: HashTable **
** **
** File name: Core\HashTable.h **
** **
** Created by: 9/22/2000 - rjm **
** **
** Description: A handy Hashtable class **
** **
*****************************************************************************/
#ifndef __CORE_LIST_HASHTABLE_H
#define __CORE_LIST_HASHTABLE_H
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#ifndef __PLAT_WN32__
#include <sys/mem/PoolManager.h>
#endif
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
template< class _V > class HashTable;
template< class _V > class HashItem
{
friend class HashTable<_V>;
private:
HashItem();
void Init();
uint32 m_key;
_V * mp_value;
HashItem<_V> * mp_next;
};
template <class _V> class HashTable
{
typedef void (*HashCallback)(_V*, void*);
public:
HashTable(uint32 numBits);
~HashTable();
// if any item exists with the same key, replace it
bool PutItem(const uint32 &key, _V *item);
// delete the item, and remove it from the table
void FlushItem(const uint32 &key);
// print all instances of an item (debugging)
void PrintItem(const uint32 &key);
// gets a pointer to requested item, returns NULL if item not in table
_V * GetItem(const uint32 &key, bool assert_if_clash = true);
_V * GetNextItemWithSameKey(const uint32 &key, _V *p_item);
void FlushAllItems(void);
void HandleCallback(HashCallback, void* pData);
int GetSize(){return m_size;}
void IterateStart();
_V * IterateNext(uint32 *pRetKey = NULL);
#ifdef __NOPT_ASSERT__
void PrintContents();
#endif
void AllowDuplicateKeys(bool allowed)
{
m_allowDuplicateKeys = allowed;
}
protected:
uint32 m_numBits; // resolution of hash table
HashItem<_V> * mp_hash_table;
int m_size; // number of entries in the table
int m_iterator_index;
HashItem<_V> * mp_iterator_item;
bool m_allowDuplicateKeys;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
template<class _V> //inline
HashTable<_V>::HashTable(uint32 numBits)
{
//Ryan("Creating HashTable");
m_numBits = numBits;
mp_hash_table = new HashItem<_V>[1<<m_numBits];
m_size = 0;
m_allowDuplicateKeys = false;
}
template<class _V> //inline
HashTable<_V>::~HashTable()
{
//Ryan("Destroying HashTable");
Dbg_AssertPtr( mp_hash_table );
if (!mp_hash_table)
return;
FlushAllItems();
// Remove the table.
// Mem::Free(mp_hash_table);
delete[] mp_hash_table;
mp_hash_table=NULL;
}
template<class _V> //inline
bool HashTable<_V>::PutItem(const uint32 &key, _V *item)
{
Dbg_AssertPtr(item);
//Ryan("putting item in Hash table\n");
Dbg_AssertPtr( mp_hash_table );
// sometimes, we want to allow checksum conflicts
// (for instance, ConvertAssets' file database)
if ( !m_allowDuplicateKeys )
{
Dbg_MsgAssert(!GetItem(key), ("item 0x%x already in hash table", key));
}
// can't add an item of 0,NULL, as that is used to indicate an empty head slot
Dbg_MsgAssert(key || item, ("Both key and item are 0 (NULL) in hash table"));
// can have a value of NULL either, as the the test below uses pEntry->mp_value == NULL
// to indicate an an empty head slot
// We could just change it to ( pEntry->mp_value || pEntry->m_key ) if NULL values are desirable
Dbg_MsgAssert( item, ("NULL item added to hash table"));
HashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];
if ( pEntry->mp_value )
{
// The main table entry is already occupied, so create a new HashEntry and
// link it in between the first and the rest.
#ifndef __PLAT_WN32__
HashItem<_V> *pNew = new (Mem::PoolManager::SCreateItem(Mem::PoolManager::vHASH_ITEM_POOL)) HashItem<_V>();
#else
HashItem<_V> *pNew = new HashItem<_V>;
#endif
pNew->m_key = key;
pNew->mp_value = item;
pNew->mp_next = pEntry->mp_next;
pEntry->mp_next = pNew;
}
else
{
// Main table entry is not occupied, so wack it in there.
pEntry->m_key = key;
pEntry->mp_value = item;
// leave pEntry->mp_next untouched
}
m_size++;
return true;
}
template<class _V> //inline
_V *HashTable<_V>::GetNextItemWithSameKey(const uint32 &key, _V *p_item)
{
Dbg_AssertPtr( mp_hash_table );
// Jump to the linked list of all entries with similar checksums.
HashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];
// Look for p_item
while (pEntry)
{
if (pEntry->m_key == key && pEntry->mp_value==p_item)
{
break;
}
pEntry=pEntry->mp_next;
}
if (!pEntry)
{
// p_item was not found.
return NULL;
}
// Found p_item, so search the rest of the list for the next element with the same key.
pEntry=pEntry->mp_next;
while (pEntry)
{
if (pEntry->m_key == key && pEntry->mp_value)
{
return pEntry->mp_value;
}
pEntry=pEntry->mp_next;
}
return NULL;
}
template<class _V> //inline
_V *HashTable<_V>::GetItem(const uint32 &key, bool assert_if_clash)
{
Dbg_AssertPtr( mp_hash_table );
// Jump to the linked list of all entries with similar checksums.
HashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];
// Scan through the small list until the matching entry is found.
// Note: the main table entry might be empty, so we still want to scan
// the linked ones
while (pEntry)
{
if (pEntry->m_key == key && pEntry->mp_value)
{
return (_V *) pEntry->mp_value;
}
pEntry=pEntry->mp_next;
}
return NULL;
}
template<class _V> //inline
void HashTable<_V>::PrintItem(const uint32 &key)
{
Dbg_AssertPtr( mp_hash_table );
// Jump to the linked list of all entries with similar checksums.
HashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];
// Scan through the small list until the matching entry is found.
int n =0;
// Note: the main table entry might be empty, so we still want to scan
// the linked ones
while (pEntry)
{
if (pEntry->m_key == key && pEntry->mp_value)
{
printf ("%d: Entry for 0x%x at %p\n", n ,key,(_V *) pEntry->mp_value);
n++;
}
pEntry=pEntry->mp_next;
}
}
template<class _V> //inline
void HashTable<_V>::FlushItem(const uint32 &key)
{
Dbg_AssertPtr( mp_hash_table );
if (!mp_hash_table)
return;
// Jump to the linked list of all entries with similar checksums.
HashItem<_V> *pEntry=&mp_hash_table[key&((1<<m_numBits)-1)];
HashItem<_V> *pLast = NULL;
// Scan through the small list until the matching entry is found.
while (pEntry)
{
HashItem<_V> *p_next_entry = pEntry->mp_next;
if (pEntry->m_key==key && pEntry->mp_value) // to allow keys of value 0, we have to skip head nodes that are 0,NULL
{
if (pLast)
{
// this is not a main table entry; this is a linked entry
pLast->mp_next = pEntry->mp_next;
#ifndef __PLAT_WN32__
Mem::PoolManager::SFreeItem(Mem::PoolManager::vHASH_ITEM_POOL, pEntry);
#else
delete pEntry;
#endif
}
else
{
// this is a main table entry, it still might be linked to something
// clear the entry to 0,NULL (see comment above about keys of value 0)
pEntry->m_key = 0;
pEntry->mp_value = NULL;
}
m_size--;
return;
}
pLast = pEntry;
pEntry = p_next_entry;
}
return;
}
template<class _V> //inline
void HashTable<_V>::FlushAllItems()
{
Dbg_AssertPtr( mp_hash_table );
if (!mp_hash_table)
return;
// Run through the table and delete any of the extra
// HashItem<_V>s.
HashItem<_V> *pMainEntry = mp_hash_table;
uint32 hashTableSize = (1<<m_numBits);
for (uint32 i=0; i<hashTableSize; ++i)
{
HashItem<_V> *pLinkedEntry = pMainEntry->mp_next;
while (pLinkedEntry)
{
HashItem<_V> *pNext = pLinkedEntry->mp_next;
#ifndef __PLAT_WN32__
Mem::PoolManager::SFreeItem(Mem::PoolManager::vHASH_ITEM_POOL, pLinkedEntry);
#else
delete pLinkedEntry;
#endif
pLinkedEntry = pNext;
}
pMainEntry->Init();
++pMainEntry;
}
m_size = 0;
}
template<class _V> //inline
void HashTable<_V>::HandleCallback(HashCallback hashCallback, void* pData)
{
HashItem<_V> *pMainEntry = mp_hash_table;
uint32 hashTableSize=(1<<m_numBits);
for (uint32 i=0; i<hashTableSize; ++i)
{
HashItem<_V> *pLinkedEntry = pMainEntry->mp_next;
while (pLinkedEntry)
{
HashItem<_V> *pNext = pLinkedEntry->mp_next;
// Mem::Free(pLinkedEntry);
if (pLinkedEntry->mp_value)
(hashCallback)((_V *) pLinkedEntry->mp_value, pData);
pLinkedEntry = pNext;
}
if (pMainEntry->mp_value)
(hashCallback)((_V *) pMainEntry->mp_value, pData);
++pMainEntry;
}
}
template<class _V> //inline
void HashTable<_V>::IterateStart()
{
m_iterator_index = -1;
mp_iterator_item = NULL;
}
template<class _V> //inline
_V * HashTable<_V>::IterateNext(uint32 *pRetKey)
{
uint32 hashTableSize=(1<<m_numBits);
// time to go to the next entry, or the first if we're just starting
if (mp_iterator_item)
// next entry in list
mp_iterator_item = mp_iterator_item->mp_next;
else if (m_iterator_index >= 0)
// we've exhausted all the lists
return NULL;
if (!mp_iterator_item)
{
// no entry in list, move on to next list
do
{
m_iterator_index++;
if (m_iterator_index >= (int) hashTableSize)
return NULL;
mp_iterator_item = mp_hash_table + m_iterator_index;
} // main entry has to contain something, or be part of a list
while (!mp_iterator_item->mp_value && !mp_iterator_item->mp_next);
if (!mp_iterator_item->mp_value)
// this must be an empty main entry, skip ahead
mp_iterator_item = mp_iterator_item->mp_next;
}
// Ken: Added this because it was hanging here once when loading the junkyard
// off CD. It was trying to dereference mp_iterator_item. Added the printf
// so we can at least see when it happens without having to go into the debugger.
if (!mp_iterator_item)
{
#ifdef __NOPT_ASSERT__
printf("Error!! NULL mp_iterator_item in IterateNext()\n");
#endif
return NULL;
}
if (pRetKey)
*pRetKey = mp_iterator_item->m_key;
return mp_iterator_item->mp_value;
}
#ifdef __NOPT_ASSERT__
template<class _V> //inline
void HashTable<_V>::PrintContents()
{
printf("Items in Hash Table:\n");
uint32 hashTableSize=(1<<m_numBits);
for (uint32 i = 0; i < hashTableSize; ++i)
{
HashItem<_V> *pEntry = mp_hash_table + i;
while(pEntry)
{
if (pEntry->mp_value)
printf(" 0x%x [%d]\n", pEntry->m_key, i);
pEntry = pEntry->mp_next;
}
}
}
#endif
template<class _V> //inline
HashItem<_V>::HashItem<_V>()
{
Init();
}
template<class _V> //inline
void HashItem<_V>::Init()
{
m_key = 0;
mp_value = NULL;
mp_next = NULL;
}
} // namespace Lst
#endif // __CORE_LIST_HASHTABLE_H

64
Code/Core/List.h Normal file
View File

@ -0,0 +1,64 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: List (Lst) **
** **
** File name: core/list.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_LIST_H
#define __CORE_LIST_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/list/node.h>
#include <core/list/head.h>
#include <core/list/search.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
#endif // __CORE_LIST_H

419
Code/Core/List/Head.h Normal file
View File

@ -0,0 +1,419 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: List (LST_) **
** **
** File name: core/list/head.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_LIST_HEAD_H
#define __CORE_LIST_HEAD_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/list/node.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/***********************************************************************
*
* Class: Head
*
* Description: Linked-list head node.
*
***********************************************************************/
nTemplateSubClass( _T, Head, Node< _T > )
{
public:
Head( void );
virtual ~Head( void );
void Merge( Head< _T >* dest ); // Source list will be empty after merge
uint CountItems( void );
Node< _T >* GetItem( uint number ); // Zero-based ( 0 will return first node )
void AddNode( Node< _T >* node ); // Using priority
void AddNodeFromTail( Node< _T >* node ); // Using priority, search backwards from tail (i.e same-priorties are appended rather than pre-pended)
bool AddUniqueSequence( Node< _T >* node ); // Only add if priority is unique
// and priority decreases
void AddToTail( Node< _T >* node );
void AddToHead( Node< _T >* node );
void RemoveAllNodes( void );
void DestroyAllNodes( void ); // ONLY USE FOR INHERITED LISTS
bool IsEmpty( void );
Node< _T >* FirstItem(); // get first node, or NULL if none
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template < class _T > inline
Head< _T >::Head( void )
: Node< _T > ( reinterpret_cast < _T* >( vHEAD_NODE ) )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Head< _T >::~Head( void )
{
Dbg_MsgAssert( IsEmpty(),( "List is not empty" ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Head< _T >::AddNode( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Dbg_MsgAssert( !node->InList (),( "Object is already in a list" ));
Node< _T >* node_ptr = this;
Priority new_pri = node->GetPri();
while (( node_ptr = node_ptr->GetNext() ))
{
if ( node_ptr->GetPri() <= new_pri )
{
node_ptr->Insert( node );
return;
}
}
Insert( node );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Head< _T >::AddNodeFromTail( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Dbg_MsgAssert( !node->InList (),( "Object is already in a list" ));
Node< _T >* node_ptr = this;
Priority new_pri = node->GetPri();
while (( node_ptr = node_ptr->GetPrev() ))
{
if ( node_ptr->GetPri() >= new_pri )
{
node_ptr->Append( node );
return;
}
}
Append( node );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Head< _T >::AddUniqueSequence( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Dbg_MsgAssert( !node->InList (),( "Object is already in a list" ));
Node< _T >* node_ptr = this;
Priority new_pri = node->GetPri();
while (( node_ptr = node_ptr->GetNext() ))
{
if ( node_ptr->GetPri() == new_pri )
{
return false;
}
else if ( node_ptr->GetPri() > new_pri )
{
node_ptr->Insert( node );
return true;
}
}
Insert( node );
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Head< _T >::Merge( Head< _T >* dest )
{
Dbg_AssertType( dest, Head< _T > );
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Dbg_MsgAssert( dest->is_head (),( "Object is not a list" ));
Node< _T >* first = next;
Node< _T >* last = prev;
Node< _T >* node = dest->GetPrev();
if ( this == first ) // source list is empty
{
return;
}
node->SetNext( first );
first->SetPrev( node );
last->SetNext( dest );
dest->SetPrev( last );
node_init(); // make the source list empty
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >* Head< _T >::GetItem( uint number )
{
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Node< _T >* node = GetNext();
while ( node )
{
if ( number-- == 0 )
{
return node;
}
node = node->GetNext();
}
Dbg_Warning( "Item requested (%d) out of range (%d)", number, CountItems() );
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Return the firs node in the list that this is the head of
template < class _T > inline
Node< _T >* Head< _T >::FirstItem( )
{
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
return GetNext();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T > inline
uint Head< _T >::CountItems( void )
{
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
uint count = 0;
Node< _T >* node = GetNext();
while ( node )
{
count++;
node = node->GetNext();
}
return count;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
void Head< _T >::RemoveAllNodes( void )
{
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Node< _T >* next_nd;
Node< _T >* node = GetNext();
while ( node )
{
next_nd = node->GetNext();
node->Remove();
node = next_nd;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
void Head< _T >::DestroyAllNodes( void )
{
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Node< _T >* next_nd;
Node< _T >* node = GetNext();
while ( node )
{
next_nd = node->GetNext();
// node->Remove();
delete node;
node = next_nd;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
void Head< _T >::AddToTail( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( this->is_head (),( "Object is not a list" ));
Dbg_MsgAssert( !node->InList (),( "Node is already in a list" ));
Insert ( node );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
void Head< _T >::AddToHead ( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( this->is_head(),(( "Object is not a list" )));
Dbg_MsgAssert( !node->InList(),(( "Node is already in a list" )));
Append( node );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
bool Head< _T >::IsEmpty( void )
{
Dbg_MsgAssert ( this->is_head(),( "Object is not a list" ));
return ( !InList() );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Lst
#endif // __CORE_LIST_HEAD_H

456
Code/Core/List/Node.h Normal file
View File

@ -0,0 +1,456 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: List (LST_) **
** **
** File name: core/list/node.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_LIST_Node_H
#define __CORE_LIST_Node_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/support.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/***********************************************************************
*
* Class: Lst::Node
*
* Description: Linked-list node.
*
***********************************************************************/
nTemplateBaseClass( _T, Node )
{
public:
// GJ: Note we have to cast vINT_MIN to an sint
// ( ((sint)vINT_MIN) / 2 ) ends up positive.
enum
{
vNORMAL_PRIORITY = 0,
vHEAD_NODE = vUINT32_MAX
};
enum
{
vSYSTEM_TASK_PRIORITY_PROCESS_MODULES = -1000,
vSYSTEM_TASK_PRIORITY_FLUSH_DEAD_OBJECTS = 1000,
};
enum
{
vLOGIC_TASK_PRIORITY_REPLAY_END_FRAME = -3000,
vLOGIC_TASK_PRIORITY_PROCESS_NETWORK_METRICS = -2500,
vLOGIC_TASK_PRIORITY_SERVER_SEND_NETWORK_DATA = -2000,
vLOGIC_TASK_PRIORITY_CLIENT_SEND_NETWORK_DATA = -2000,
vLOGIC_TASK_PRIORITY_TIMEOUT_CONNECTIONS = -2000,
vLOGIC_TASK_PRIORITY_CLIENT_ADD_NEW_PLAYERS = -2000,
vLOGIC_TASK_PRIORITY_SERVER_ADD_NEW_PLAYERS = -2000,
vLOGIC_TASK_PRIORITY_FRONTEND = -2000,
vLOGIC_TASK_PRIORITY_SCRIPT_DEBUGGER = -1500,
vLOGIC_TASK_PRIORITY_LOCKED_OBJECT_MANAGER_LOGIC = -1100,
vLOGIC_TASK_PRIORITY_PARTICLE_MANAGER_LOGIC = -1000,
vLOGIC_TASK_PRIORITY_HANDLE_KEYBOARD = -1000,
vLOGIC_TASK_PRIORITY_OBJECT_UPDATE = -1000,
vLOGIC_TASK_PRIORITY_SCORE_UPDATE = -1000,
vLOGIC_TASK_PRIORITY_COMPOSITE_MANAGER = -900,
vLOGIC_TASK_PRIORITY_PROCESS_NETWORK_DATA = 0,
vLOGIC_TASK_PRIORITY_SKATER_SERVER = 1000,
vLOGIC_TASK_PRIORITY_TRANSFER_NETWORK_DATA = 1000,
vLOGIC_TASK_PRIORITY_RECEIVE_NETWORK_DATA = 1000,
vLOGIC_TASK_PRIORITY_PROCESS_HANDLERS = 2000,
vLOGIC_TASK_PRIORITY_REPLAY_START_FRAME = 3000,
};
enum
{
vDISPLAY_TASK_PRIORITY_PARK_EDITOR_DISPLAY = -1000,
vDISPLAY_TASK_PRIORITY_CPARKEDITOR_DISPLAY = -1000,
vDISPLAY_TASK_PRIORITY_IMAGE_VIEWER_DISPLAY = -1000,
vDISPLAY_TASK_PRIORITY_PANEL_DISPLAY = -500,
};
enum
{
vHANDLER_PRIORITY_OBSERVER_INPUT_LOGIC = -1000,
vHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC0 = -1000,
vHANDLER_PRIORITY_FRONTEND_INPUT_LOGIC1 = -1000,
vHANDLER_PRIORITY_IMAGE_VIEWER_INPUT_LOGIC = 1000,
vHANDLER_PRIORITY_VIEWER_SHIFT_INPUT_LOGIC = 1000,
};
typedef sint Priority;
Node ( _T* d, Priority p = vNORMAL_PRIORITY );
virtual ~Node ( void );
void Insert ( Node< _T >* node );
void Append ( Node< _T >* node );
void Remove ( void );
void SetPri ( const Priority priority );
void SetNext ( Node< _T >* node );
void SetPrev ( Node< _T >* node );
Priority GetPri ( void ) const;
Node< _T >* GetNext ( void ) const;
Node< _T >* GetPrev ( void ) const;
_T* GetData ( void ) const;
Node< _T >* LoopNext ( void ) const;
Node< _T >* LoopPrev ( void ) const;
bool InList ( void ) const;
protected:
bool is_head ( void ) const;
void node_init ( void );
private:
_T* data;
Priority pri;
Node< _T >* next;
Node< _T >* prev;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Inline Functions **
*****************************************************************************/
template < class _T > inline
void Node< _T >::node_init( void )
{
next = this;
prev = this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Node< _T >::is_head( void ) const
{
return ( data == reinterpret_cast<void*>( vHEAD_NODE ));
}
/*****************************************************************************
** Public Inline Functions **
*****************************************************************************/
template < class _T > inline
Node< _T >::Node( _T* d, Priority p )
: data( d ), pri( p )
{
node_init();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Must define inline functions before they are used
template < class _T > inline
void Node< _T >::Remove( void )
{
prev->next = next;
next->prev = prev;
node_init(); // so we know that the node is not in a list
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >::~Node( void )
{
Remove();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Mick: Moved this here from the end of the file
// as it's intended to b inline
// yet it is used by other functions below
template < class _T > inline
bool Node< _T >::InList( void ) const
{
return ( prev != this );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Node< _T >::Insert ( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( !node->InList(),("node is already in a list" ));
node->prev = prev;
node->next = this;
prev->next = node;
prev = node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Node< _T >::Append( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
Dbg_MsgAssert( !node->InList(),( "node is already in a list" ));
node->prev = this;
node->next = next;
next->prev = node;
next = node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Node< _T >::SetPri( const Priority priority )
{
pri = priority;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Node< _T >::SetNext( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
next = node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Node< _T >::SetPrev( Node< _T >* node )
{
Dbg_AssertType( node, Node< _T > );
prev = node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
typename Node< _T >::Priority Node< _T >::GetPri( void ) const
{
return pri;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >* Node< _T >::GetNext( void ) const
{
if ( next->is_head() )
{
return NULL;
}
return next;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >* Node< _T >::GetPrev( void ) const
{
if ( prev->is_head() )
{
return NULL;
}
return prev;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_T* Node< _T >::GetData( void ) const
{
return data;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >* Node< _T >::LoopNext( void ) const
{
Node< _T >* next_node = next;
if ( next_node->is_head() )
{
next_node = next_node->next; // skip head node
if ( next_node->is_head() )
{
return NULL; // list is empty
}
}
return next_node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Node< _T >* Node< _T >::LoopPrev( void ) const
{
Node< _T >* prev_node = prev;
if ( prev_node->is_head() )
{
prev_node = prev_node->prev; // skip head node
if ( prev_node->is_head() )
{
return NULL; // list is empty
}
}
return prev_node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Lst
#endif // __CORE_LIST_Node_H

192
Code/Core/List/Search.h Normal file
View File

@ -0,0 +1,192 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: List (LST_) **
** **
** File name: core/list/search.h **
** **
** Created: 04/02/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_LIST_SEARCH_H
#define __CORE_LIST_SEARCH_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/list/node.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
nTemplateBaseClass ( _T, Search )
{
public:
Search ( void );
virtual ~Search ( void );
_T* FirstItem ( Head<_T>& head );
_T* LastItem ( Head<_T>& head );
_T* NextItem ( void );
_T* PrevItem ( void );
private:
Node< _T >* node;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template <class _T> inline
Search<_T>::Search ( void )
: node ( NULL )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
Search<_T>::~Search ( void )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
_T* Search<_T>::FirstItem ( Head<_T>& head )
{
Dbg_AssertType ( &head, Head<_T> );
node = &head;
return ( NextItem () );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
_T* Search<_T>::LastItem ( Head<_T>& head )
{
Dbg_AssertType ( &head, Head<_T> );
node = &head;
return ( PrevItem () );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
_T* Search<_T>::NextItem ( void )
{
Dbg_AssertType ( node, Node< _T > );
node = node->GetNext();
if ( !node )
{
return NULL;
}
Dbg_AssertType ( node, Node<_T> );
return ( node->GetData() );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template <class _T> inline
_T* Search<_T>::PrevItem ( void )
{
Dbg_AssertType ( node, Node< _T > );
node = node->GetPrev();
if ( !node )
{
return NULL;
}
Dbg_AssertType ( node, Node<_T> );
return ( node->GetData() );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Lst
#endif // __CORE_LIST_SEARCH_H

73
Code/Core/List/list.cpp Normal file
View File

@ -0,0 +1,73 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: List (Lst) **
** **
** File name: list.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: List management code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/

88
Code/Core/LookupTable.cpp Normal file
View File

@ -0,0 +1,88 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: List **
** **
** File name: Core\List\LookupTable.cpp **
** **
** Created by: 9/22/2000 - rjm **
** **
** Description: A Lookuptable **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/string/cstring.h>
#include <core/lookuptable.h>
//
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************************
*
* Function:
*
* Description: Default constructor
*
* Parameters:
*
*****************************************************************************/
} // namespace Lst

426
Code/Core/LookupTable.h Normal file
View File

@ -0,0 +1,426 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: LookupTable **
** **
** File name: Core\LookupTable.h **
** **
** Created by: 9/22/2000 - rjm **
** **
** Description: A handy Lookuptable class **
** **
*****************************************************************************/
#ifndef __CORE_LIST_LOOKUPTABLE_H
#define __CORE_LIST_LOOKUPTABLE_H
#ifndef __CORE_CRC_H
#include <core/crc.h>
#endif
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/****************************************************************************
*
* Class: LookupItem
*
* Description: Used to represent an item in a Lookup table.
*
* Usage:
*
*
*
****************************************************************************/
// forward declaration
template< class _V > class LookupTable;
//nTemplateBaseClass2(_K, _V, LookupItem)
template< class _V > class LookupItem
{
// Dbg_TemplateBaseClass2(_K, _V, LookupItem);
friend class LookupTable<_V>;
private:
LookupItem();
int m_key;
_V * mp_value;
LookupItem<_V> * mp_next;
};
nTemplateBaseClass(_V, LookupTable)
{
Dbg_TemplateBaseClass(_V, LookupTable);
public:
LookupTable(int size=0); // Mick, size is not used, so give it default until we get rid of it
~LookupTable();
// if any item exists with the same key, replace it
bool PutItem(const int &key, _V *item);
// gets a pointer to requested item, returns NULL if item not in table
_V *GetItem(const int &key);
// gets a pointer to requested item, returns NULL if item not in table
_V *GetItemByIndex(const int &index, int *pKey = NULL);
int getSize() {return m_size;}
// removes item from table, calls its destructor if requested
void FlushItem(const int &key);
void flushAllItems();
private:
int m_size;
LookupItem<_V> * mp_list; // first item in list
LookupItem<_V> * mp_last; // last item in list
LookupItem<_V> * mp_current; // Pointer to current item in this table, NULL if invalid
int m_currentIndex; // the index of this item. Only valid if mp_current is not NULL
};
template<class _V>
class StringLookupTable : public LookupTable<_V>
{
//Dbg_TemplateBaseClass2(_K, _V, LookupItem);
public:
StringLookupTable(int size);
bool PutItem(const char *stringKey, _V *item);
_V *GetItem(const char *stringKey);
void FlushItem(const char *stringKey);
};
template<class _V>
class LookupTableDestroyer
{
public:
LookupTableDestroyer(LookupTable<_V> *pTable);
void DeleteTableContents();
private:
LookupTable<_V> * mp_table;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
template<class _V> //inline
LookupItem<_V>::LookupItem()
{
mp_value = NULL;
mp_next = NULL;
}
template<class _V> //inline
LookupTable<_V>::LookupTable(int size=0)
{
m_size = 0;
mp_list = NULL;
mp_current = NULL; // initialized invalid, so we don't try to use it
}
template<class _V> //inline
LookupTable<_V>::~LookupTable()
{
flushAllItems();
}
template<class _V> //inline
bool LookupTable<_V>::PutItem(const int &key, _V *item)
{
Dbg_AssertPtr(item);
//Ryan("putting item in lookup table\n");
# ifdef __NOPT_DEBUG__
if (GetItem(key)) return false;
# endif
LookupItem<_V> *pItem = new LookupItem<_V>;
pItem->mp_value = item;
pItem->m_key = key;
if (!mp_list)
mp_list = pItem;
else
mp_last->mp_next = pItem;
mp_last = pItem;
m_size++;
mp_current = NULL; // no longer valid
return true;
}
template<class _V> //inline
_V *LookupTable<_V>::GetItem(const int &key)
{
LookupItem<_V> *pItem = mp_list;
mp_current = NULL; // set invalid now, so if not found, then it will be correctly invalid
m_currentIndex = 0; // index should be 0, for the first item
while(pItem)
{
if (pItem->m_key == key)
{
mp_current = pItem; // we have a valid current, and hence index
return pItem->mp_value;
}
m_currentIndex++; // update index, in case we find the item
pItem = pItem->mp_next;
}
//printf("returning NULL from GetItem()\n");
// warning should be given by calling function, if necessary
//Dbg_Warning("Item not found in lookup table");
return NULL;
}
template<class _V> //inline
_V *LookupTable<_V>::GetItemByIndex(const int &index, int *pKey)
{
// size must be at least 1
Dbg_MsgAssert(index >= 0 && index < m_size,( "bad index %d", index));
// if we have a valid mp_current, then check if we can use that (for speed)
if (mp_current)
{
// is it the same as last time?
if (m_currentIndex == index)
{
// It's this one, so just leave it alone
}
else if (m_currentIndex < index)
{
// need to step forward until we find the correct one
// this is the most likely scenario if
// we are using GetItemByIndex in a for loop
// really we need an interator access class
// but this should be similar, in terms of code speed
while (m_currentIndex < index)
{
m_currentIndex++;
mp_current = mp_current->mp_next;
}
}
else
{
// otherwise, we need to start again, so invalidate mp_current
mp_current = NULL;
}
}
// if we don't have a valid mp_current at this point, then we need
// to start searching from the start again
if (!mp_current)
{
LookupItem<_V> *pItem = mp_list;
for (int i = 0; i < index; i++)
{
pItem = pItem->mp_next;
}
m_currentIndex = index;
mp_current = pItem;
}
// if they want us to returnt he key, then poke it into the supplied destination
if ( pKey )
*pKey = mp_current->m_key;
// the current value is correct
return mp_current->mp_value;
}
template<class _V> //inline
void LookupTable<_V>::FlushItem(const int &key)
{
mp_current = NULL; // No longer valid
LookupItem<_V> *pItem = mp_list;
LookupItem<_V> *prev = NULL;
while(pItem)
{
if (pItem->m_key == key)
{
if (prev)
prev->mp_next = pItem->mp_next;
else
mp_list = pItem->mp_next;
if (mp_last == pItem)
mp_last = prev;
delete pItem;
m_size--;
return;
}
prev = pItem;
pItem = pItem->mp_next;
}
}
template<class _V> //inline
void LookupTable<_V>::flushAllItems()
{
LookupItem<_V> *pItem = mp_list;
while(pItem)
{
LookupItem<_V> *pNext = pItem->mp_next;
delete pItem;
pItem = pNext;
}
mp_list = NULL;
mp_current = NULL;
m_size = 0;
}
/*
int m_size;
LookupItem<_K, _V> *m_array;
_K m_key;
_V *mp_value;
*/
template<class _V> //inline
StringLookupTable<_V>::StringLookupTable(int size) :
LookupTable<_V>(size)
{
}
template<class _V> //inline
bool StringLookupTable<_V>::PutItem(const char *stringKey, _V *item)
{
int key = Crc::GenerateCRCFromString(stringKey);
return LookupTable<_V>::PutItem(key, item);
}
template<class _V> //inline
_V *StringLookupTable<_V>::GetItem(const char *stringKey)
{
int key = Crc::GenerateCRCFromString(stringKey);
return LookupTable<_V>::GetItem(key);
}
template<class _V> //inline
void StringLookupTable<_V>::FlushItem(const char *stringKey)
{
int key = Crc::GenerateCRCFromString(stringKey);
LookupTable<_V>::FlushItem(key);
}
template<class _V> //inline
LookupTableDestroyer<_V>::LookupTableDestroyer(LookupTable<_V> *pTable)
{
mp_table = pTable;
}
template<class _V> inline
void LookupTableDestroyer<_V>::DeleteTableContents()
{
int num_items = mp_table->getSize();
for (int i = 0; i < num_items; i++)
{
int key;
// since we are flushing items out of the table as we go,
// we should always grab the first one
_V *pItem = mp_table->GetItemByIndex(0, &key);
mp_table->FlushItem(key);
if (pItem) delete pItem;
}
}
} // namespace Lst
#endif // __CORE_LIST_LOOKUPTABLE_H

158
Code/Core/Math/Xbox/sse.h Normal file
View File

@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
// File: SSE.h
//
// Desc: P3 SSE conversions and estimates
//
// Hist: 1.7.03 - Created
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#ifndef P3_SSE
#define P3_SSE
//-----------------------------------------------------------------------------
// Name: Ftoi_ASM
// Desc: SSE float to int conversion. Note that no control word needs to be
// set to round down
//-----------------------------------------------------------------------------
__forceinline int Ftoi_ASM( const float f )
{
__asm cvttss2si eax, f // return int(f)
}
//-----------------------------------------------------------------------------
// Name: ReciprocalEstimate_ASM
// Desc: SSE reciprocal estimate, accurate to 12 significant bits of
// the mantissa
//-----------------------------------------------------------------------------
__forceinline float ReciprocalEstimate_ASM( const float f )
{
float rec;
__asm rcpss xmm0, f // xmm0 = rcpss(f)
__asm movss rec , xmm0 // return xmm0
return rec;
}
//-----------------------------------------------------------------------------
// Name: ReciprocalSqrtEstimate_ASM
// Desc: SSE reciprocal square root estimate, accurate to 12 significant
// bits of the mantissa
//-----------------------------------------------------------------------------
__forceinline float ReciprocalSqrtEstimate_ASM( const float f )
{
float recsqrt;
__asm rsqrtss xmm0, f // xmm0 = rsqrtss(f)
__asm movss recsqrt, xmm0 // return xmm0
return recsqrt;
}
//-----------------------------------------------------------------------------
// Name: SqrtEstimae_ASM
// Desc: SSE square root estimate, accurate to 12 significant bits of
// the mantissa. Note that a check for zero must be made since
// sqrt(0) == 0 but 1/sqrt(0) = inf
//-----------------------------------------------------------------------------
__forceinline float SqrtEstimate_ASM( const float f )
{
float recsqrt;
__asm movss xmm0,f // xmm0 = f
__asm rsqrtss xmm1, xmm0 // xmm1 = rsqrtss(f)
__asm mulss xmm1, xmm0 // xmm1 = rsqrtss(f) * f = sqrt(f)
__asm xorps xmm2, xmm2 // xmm2 = 0
__asm cmpneqss xmm2, xmm0 // xmm2 = (f != 0 ? 1s : 0s)
__asm andps xmm1, xmm2 // xmm1 = xmm1 & xmm2
__asm movss recsqrt, xmm1 // return xmm1
return recsqrt;
}
//-----------------------------------------------------------------------------
// Name: ReciprocalEstimateNR_ASM
// Desc: SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
// bits of the mantissa
// One Newtown-Raphson Iteration:
// f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
//-----------------------------------------------------------------------------
__forceinline float ReciprocalEstimateNR_ASM( const float f )
{
float rec;
__asm rcpss xmm0, f // xmm0 = rcpss(f)
__asm movss xmm1, f // xmm1 = f
__asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f)
__asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f)
__asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f)
__asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f)
// - f * rcpss(f) * rcpss(f)
__asm movss rec, xmm0 // return xmm0
return rec;
}
//-----------------------------------------------------------------------------
// Newton-Rapson square root iteration constants
//-----------------------------------------------------------------------------
const float g_SqrtNRConst[2] = {0.5f, 3.0f};
//-----------------------------------------------------------------------------
// Name: ReciprocalSqrtEstimateNR_ASM
// Desc: SSE Newton-Raphson reciprocal square root estimate, accurate to 23
// significant bits of the mantissa
// One Newtown-Raphson Iteration:
// f(i+1) = 0.5 * rsqrtss(f) * (3.0 - (f * rsqrtss(f) * rsqrtss(f))
// NOTE: rsqrtss(f) * rsqrtss(f) != rcpss(f) (presision is not maintained)
//-----------------------------------------------------------------------------
__forceinline float ReciprocalSqrtEstimateNR_ASM( const float f )
{
float recsqrt;
__asm rsqrtss xmm0, f // xmm0 = rsqrtss(f)
__asm movss xmm1, f // xmm1 = f
__asm mulss xmm1, xmm0 // xmm1 = f * rsqrtss(f)
__asm movss xmm2, g_SqrtNRConst+4 // xmm2 = 3.0f
__asm mulss xmm1, xmm0 // xmm1 = f * rsqrtss(f) * rsqrtss(f)
__asm mulss xmm0, g_SqrtNRConst // xmm0 = 0.5f * rsqrtss(f)
__asm subss xmm2, xmm1 // xmm2 = 3.0f -
// f * rsqrtss(f) * rsqrtss(f)
__asm mulss xmm0, xmm2 // xmm0 = 0.5 * rsqrtss(f)
// * (3.0 - (f * rsqrtss(f) * rsqrtss(f))
__asm movss recsqrt, xmm0 // return xmm0
return recsqrt;
}
//-----------------------------------------------------------------------------
// Name: SqrtEstimateNR_ASM
// Desc: SSE Newton-Raphson square root estimate, accurate to 23 significant
// bits of the mantissa
// NOTE: x/sqrt(x) = sqrt(x)
// One Newtown-Raphson Iteration (for 1/sqrt(x)) :
// f(i+1) = 0.5 * rsqrtss(f) * (3.0 - (f * rsqrtss(f) * rsqrtss(f))
// NOTE: rsqrtss(f) * rsqrtss(f) != rcpss(f) (presision is not maintained)
//-----------------------------------------------------------------------------
__forceinline float SqrtEstimateNR_ASM( const float f )
{
float recsqrt;
__asm rsqrtss xmm0, f // xmm0 = rsqrtss(f)
__asm movss xmm1, f // xmm1 = f
__asm mulss xmm1, xmm0 // xmm1 = f * rsqrtss(f)
__asm movss xmm2, g_SqrtNRConst+4 // xmm2 = 3.0f
__asm mulss xmm1, xmm0 // xmm1 = f * rsqrtss(f) * rsqrtss(f)
__asm mulss xmm0, g_SqrtNRConst // xmm0 = 0.5f * rsqrtss(f)
__asm subss xmm2, xmm1 // xmm2 = 3.0f -
// f * rsqrtss(f) * rsqrtss(f)
__asm mulss xmm0, xmm2 // xmm0 = 0.5 * rsqrtss(f)
// * (3.0 - (f * rsqrtss(f) * rsqrtss(f))
__asm xorps xmm1, xmm1 // xmm1 = 0
__asm mulss xmm0, f // xmm0 = sqrt(f)
__asm cmpneqss xmm1, f // xmm1 = (f != 0 ? 1s : 0s)
__asm andps xmm0, xmm1 // xmm0 = xmm1 & xmm2
__asm movss recsqrt, xmm0 // return xmm0
return recsqrt;
}
#endif // P3_SSE

562
Code/Core/Math/geometry.cpp Normal file
View File

@ -0,0 +1,562 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Geometry (MTH) **
** **
** File name: Geometry.cpp **
** **
** Created by: 11/14/00 - Mick **
** **
** Description: Math **
// This module handles the representation and manipulation of line segements
// and planes
//
// a line segment (Mth::Line) is defined by two points, m_start and m_end
//
// a plane is defined by a point and a normal
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/math.h>
#include <core/math/geometry.h>
#include <gfx/debuggfx.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** DBG Information **
*****************************************************************************/
//
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
Line::Line()
{
}
Line::Line ( const Vector &start, const Vector &end )
{
m_start = start;
m_end = end;
}
Plane::Plane()
{
}
Plane::Plane (const Vector &point, const Vector &normal)
{
m_point = point;
m_normal = normal;
}
Rectangle::Rectangle()
{
}
Rectangle::Rectangle ( const Vector& corner, const Vector& first_edge, const Vector& second_edge )
{
m_corner = corner;
m_first_edge = first_edge;
m_second_edge = second_edge;
}
/*
Calculate the line segment PaPb that is the shortest route between
two lines P1P2 and P3P4. Calculate also the values of mua and mub where
Pa = P1 + mua (P2 - P1)
Pb = P3 + mub (P4 - P3)
Return FALSE if no solution exists.
original algorithm from http://www.swin.edu.au/astronomy/pbourke/geometry/lineline3d/
note that I (Mick) modified it to clamp the points to within the line segments
if you remove the "Clamp" calls below, then the lines will be assumed to be
of infinite length
*/
#define EPS 0.00001f
bool LineLineIntersect( Line & l1, Line & l2, Vector *pa, Vector *pb, float *mua, float *mub, bool clamp )
{
Vector &p1 = l1.m_start;
Vector &p2 = l1.m_end;
Vector &p3 = l2.m_start;
Vector &p4 = l2.m_end;
Vector p13,p43,p21;
float d1343,d4321,d1321,d4343,d2121;
float numer,denom;
p13 = p1 - p3;
p43 = p4 - p3;
if (Abs(p43[X]) < EPS && Abs(p43[Y]) < EPS && Abs(p43[Z]) < EPS)
return(false);
p21 = p2 - p1;
if (Abs(p21[X]) < EPS && Abs(p21[Y]) < EPS && Abs(p21[Z]) < EPS)
return(false);
d1343 = DotProduct(p13,p43);
d4321 = DotProduct(p43,p21);
d1321 = DotProduct(p13,p21);
d4343 = DotProduct(p43,p43);
d2121 = DotProduct(p21,p21);
denom = d2121 * d4343 - d4321 * d4321;
if (Abs(denom) < EPS)
return(false);
numer = d1343 * d4321 - d1321 * d4343;
*mua = numer / denom;
if( clamp )
{
*mua = Clamp(*mua,0.0f,1.0f);
}
*mub = (d1343 + d4321 * (*mua)) / d4343;
if( clamp )
{
*mub = Clamp(*mub,0.0f,1.0f);
}
*pa = p1 + (*mua * p21);
*pb = p3 + (*mub * p43);
return(true);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CBBox::CBBox()
{
Reset();
}
CBBox::CBBox(const Vector &point)
{
Set(point, point);
}
CBBox::CBBox(const Vector &min, const Vector &max)
{
Set(min, max);
}
void CBBox::AddPoint(const Vector &point)
{
// Adjust min/max points
if (point[X] < m_min[X])
m_min[X] = point[X];
if (point[Y] < m_min[Y])
m_min[Y] = point[Y];
if (point[Z] < m_min[Z])
m_min[Z] = point[Z];
if (point[X] > m_max[X])
m_max[X] = point[X];
if (point[Y] > m_max[Y])
m_max[Y] = point[Y];
if (point[Z] > m_max[Z])
m_max[Z] = point[Z];
}
// Returns number of axes within and flags for which ones
int CBBox::WithinAxes(const Vector &point, uint32 &axis_flags) const
{
int number_of_axes = 0;
axis_flags = 0;
if ((point[X] >= m_min[X]) && (point[X] <= m_max[X]))
{
number_of_axes++;
axis_flags |= 1 << X;
}
if ((point[Y] >= m_min[Y]) && (point[Y] <= m_max[Y]))
{
number_of_axes++;
axis_flags |= 1 << Y;
}
if ((point[Z] >= m_min[Z]) && (point[Z] <= m_max[Z]))
{
number_of_axes++;
axis_flags |= 1 << Z;
}
return number_of_axes;
}
void CBBox::DebugRender(uint32 rgba, int frames) const
{
// Min YZ square
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_min[Y],m_min[Z]),Mth::Vector(m_min[X],m_min[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_min[Y],m_max[Z]),Mth::Vector(m_min[X],m_max[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_max[Y],m_max[Z]),Mth::Vector(m_min[X],m_max[Y],m_min[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_max[Y],m_min[Z]),Mth::Vector(m_min[X],m_min[Y],m_min[Z]),rgba,rgba,frames);
// Max YZ square
Gfx::AddDebugLine(Mth::Vector(m_max[X],m_min[Y],m_min[Z]),Mth::Vector(m_max[X],m_min[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_max[X],m_min[Y],m_max[Z]),Mth::Vector(m_max[X],m_max[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_max[X],m_max[Y],m_max[Z]),Mth::Vector(m_max[X],m_max[Y],m_min[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_max[X],m_max[Y],m_min[Z]),Mth::Vector(m_max[X],m_min[Y],m_min[Z]),rgba,rgba,frames);
// lines joining corners
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_min[Y],m_min[Z]),Mth::Vector(m_max[X],m_min[Y],m_min[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_min[Y],m_max[Z]),Mth::Vector(m_max[X],m_min[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_max[Y],m_max[Z]),Mth::Vector(m_max[X],m_max[Y],m_max[Z]),rgba,rgba,frames);
Gfx::AddDebugLine(Mth::Vector(m_min[X],m_max[Y],m_min[Z]),Mth::Vector(m_max[X],m_max[Y],m_min[Z]),rgba,rgba,frames);
}
void CBBox::DebugRender(const Mth::Matrix & transform, uint32 rgba, int frames) const
{
uint32 rgba_min = 0xFF000080;
uint32 rgba_max = 0x0000FF80;
Mth::Vector min_yz_1(m_min[X], m_min[Y], m_min[Z]);
Mth::Vector min_yz_2(m_min[X], m_min[Y], m_max[Z]);
Mth::Vector min_yz_3(m_min[X], m_max[Y], m_max[Z]);
Mth::Vector min_yz_4(m_min[X], m_max[Y], m_min[Z]);
Mth::Vector max_yz_1(m_max[X], m_min[Y], m_min[Z]);
Mth::Vector max_yz_2(m_max[X], m_min[Y], m_max[Z]);
Mth::Vector max_yz_3(m_max[X], m_max[Y], m_max[Z]);
Mth::Vector max_yz_4(m_max[X], m_max[Y], m_min[Z]);
// Transform
min_yz_1 = transform.Transform(min_yz_1);
min_yz_2 = transform.Transform(min_yz_2);
min_yz_3 = transform.Transform(min_yz_3);
min_yz_4 = transform.Transform(min_yz_4);
max_yz_1 = transform.Transform(max_yz_1);
max_yz_2 = transform.Transform(max_yz_2);
max_yz_3 = transform.Transform(max_yz_3);
max_yz_4 = transform.Transform(max_yz_4);
// Min YZ square
Gfx::AddDebugLine(min_yz_1, min_yz_2,rgba_min,rgba_min,frames);
Gfx::AddDebugLine(min_yz_2, min_yz_3,rgba_min,rgba_min,frames);
Gfx::AddDebugLine(min_yz_3, min_yz_4,rgba_min,rgba_min,frames);
Gfx::AddDebugLine(min_yz_4, min_yz_1,rgba_min,rgba_min,frames);
// Max YZ square
Gfx::AddDebugLine(max_yz_1, max_yz_2,rgba_max,rgba_max,frames);
Gfx::AddDebugLine(max_yz_2, max_yz_3,rgba_max,rgba_max,frames);
Gfx::AddDebugLine(max_yz_3, max_yz_4,rgba_max,rgba_max,frames);
Gfx::AddDebugLine(max_yz_4, max_yz_1,rgba_max,rgba_max,frames);
// lines joining corners
Gfx::AddDebugLine(min_yz_1, max_yz_1,rgba,rgba,frames);
Gfx::AddDebugLine(min_yz_2, max_yz_2,rgba,rgba,frames);
Gfx::AddDebugLine(min_yz_3, max_yz_3,rgba,rgba,frames);
Gfx::AddDebugLine(min_yz_4, max_yz_4,rgba,rgba,frames);
}
bool CBBox::LineIntersect( const Mth::Line &line, Mth::Vector &point, Mth::Vector &normal ) const
{
bool start_point_within = Within(line.m_start);
bool end_point_within = Within(line.m_end);
// Doesn't intersect side if both points within
if (start_point_within && end_point_within)
{
return false;
}
// Trivial rejection.
if ((line.m_start[Y] > m_max[Y]) && (line.m_end[Y] > m_max[Y])) return false;
if ((line.m_start[Y] < m_min[Y]) && (line.m_end[Y] < m_min[Y])) return false;
if ((line.m_start[X] > m_max[X]) && (line.m_end[X] > m_max[X])) return false;
if ((line.m_start[X] < m_min[X]) && (line.m_end[X] < m_min[X])) return false;
if ((line.m_start[Z] > m_max[Z]) && (line.m_end[Z] > m_max[Z])) return false;
if ((line.m_start[Z] < m_min[Z]) && (line.m_end[Z] < m_min[Z])) return false;
float dx = line.m_end[X] - line.m_start[X];
float dy = line.m_end[Y] - line.m_start[Y];
float dz = line.m_end[Z] - line.m_start[Z];
// avoid divide by zeros.
if ( !dx )
{
dx = ( 0.000001f );
}
if ( !dy )
{
dy = ( 0.000001f );
}
if ( !dz )
{
dz = ( 0.000001f );
}
//
// Garrett: I back-face cull 3 of the sides to reduce the calculations and keep
// the collisions down to one side.
// Check the max-x face.
if (line.m_start[X] > m_max[X] && line.m_end[X] < m_max[X] && (dx < 0.0f))
{
// It crosses the plane of the face, so calculate the y & z coords
// of the intersection and see if they are in the face,
float d=m_max[X] - line.m_start[X];
float y=d*dy/dx + line.m_start[Y];
float z=d*dz/dx + line.m_start[Z];
if (y < m_max[Y] && y > m_min[Y] && z < m_max[Z] && z > m_min[Z])
{
// It does collide!
point = Mth::Vector(m_max[X], y, z, 1.0f);
normal = Mth::Vector(1.0f, 0.0f, 0.0f, 0.0f);
return true;
}
}
// Check the min-x face.
if (line.m_start[X] < m_min[X] && line.m_end[X] > m_min[X] && (dx > 0.0f))
{
// It crosses the plane of the face, so calculate the y & z coords
// of the intersection and see if they are in the face,
float d=m_min[X] - line.m_start[X];
float y=d*dy/dx + line.m_start[Y];
float z=d*dz/dx + line.m_start[Z];
if (y < m_max[Y] && y > m_min[Y] && z < m_max[Z] && z > m_min[Z])
{
// It does collide!
point = Mth::Vector(m_min[X], y, z, 1.0f);
normal = Mth::Vector(-1.0f, 0.0f, 0.0f, 0.0f);
return true;
}
}
// Check the max-y face.
if (line.m_start[Y] > m_max[Y] && line.m_end[Y] < m_max[Y] && (dy < 0.0f))
{
// It crosses the plane of the face, so calculate the x & z coords
// of the intersection and see if they are in the face,
float d=m_max[Y] - line.m_start[Y];
float x=d*dx/dy + line.m_start[X];
float z=d*dz/dy + line.m_start[Z];
if (x < m_max[X] && x > m_min[X] && z < m_max[Z] && z > m_min[Z])
{
// It does collide!
point = Mth::Vector(x, m_max[Y], z, 1.0f);
normal = Mth::Vector(0.0f, 1.0f, 0.0f, 0.0f);
return true;
}
}
// Check the min-y face.
if (line.m_start[Y] < m_min[Y] && line.m_end[Y] > m_min[Y] && (dy > 0.0f))
{
// It crosses the plane of the face, so calculate the x & z coords
// of the intersection and see if they are in the face,
float d=m_min[Y] - line.m_start[Y];
float x=d*dx/dy + line.m_start[X];
float z=d*dz/dy + line.m_start[Z];
if (x < m_max[X] && x > m_min[X] && z < m_max[Z] && z > m_min[Z])
{
// It does collide!
point = Mth::Vector(x, m_min[Y], z, 1.0f);
normal = Mth::Vector(0.0f, -1.0f, 0.0f, 0.0f);
return true;
}
}
// Check the max-z face.
if (line.m_start[Z] > m_max[Z] && line.m_end[Z] < m_max[Z] && (dz < 0.0f))
{
// It crosses the plane of the face, so calculate the x & y coords
// of the intersection and see if they are in the face,
float d=m_max[Z] - line.m_start[Z];
float x=d*dx/dz + line.m_start[X];
float y=d*dy/dz + line.m_start[Y];
if (x < m_max[X] && x > m_min[X] && y < m_max[Y] && y > m_min[Y])
{
// It does collide!
point = Mth::Vector(x, y, m_max[Z], 1.0f);
normal = Mth::Vector(0.0f, 0.0f, 1.0f, 0.0f);
return true;
}
}
// Check the min-z face.
if (line.m_start[Z] < m_min[Z] && line.m_end[Z] > m_min[Z] && (dz > 0.0f))
{
// It crosses the plane of the face, so calculate the x & y coords
// of the intersection and see if they are in the face,
float d=m_min[Z] - line.m_start[Z];
float x=d*dx/dz + line.m_start[X];
float y=d*dy/dz + line.m_start[Y];
if (x < m_max[X] && x > m_min[X] && y < m_max[Y] && y > m_min[Y])
{
// It does collide!
point = Mth::Vector(x, y, m_min[Z], 1.0f);
normal = Mth::Vector(0.0f, 0.0f, -1.0f, 0.0f);
return true;
}
}
return false;
}
void CBBox::GetClosestIntersectPoint(const Mth::Vector &pos, Mth::Vector &point) const
{
uint32 axes_within_flags;
int axes_within = WithinAxes(pos, axes_within_flags);
if (axes_within == 3)
{
float closest_dist = -1.0f;
int closest_axis = -1;
float closest_axis_coord = 0.0f; // Value of the minimum axis coordinate
// Find the closest rectangle and move the point to that rectangle to find the intersection
// point.
for (int axis = X; axis <= Z; axis++)
{
float min_to_pos_dist = pos[axis] - m_min[axis];
float max_to_pos_dist = m_max[axis] - pos[axis];
Dbg_Assert(min_to_pos_dist >= 0.0f);
Dbg_Assert(max_to_pos_dist >= 0.0f);
float min_dist;
float min_coord;
// Figure out the closest distance
if (min_to_pos_dist < max_to_pos_dist)
{
min_dist = min_to_pos_dist;
min_coord = m_min[axis];
}
else
{
min_dist = max_to_pos_dist;
min_coord = m_max[axis];
}
// See if this is the first axis or if this one is closer
if ((axis == X) || (min_dist < closest_dist))
{
closest_axis = axis;
closest_dist = min_dist;
closest_axis_coord = min_coord;
}
}
Dbg_Assert((closest_axis >= X) && (closest_axis <= Z));
Dbg_Assert(closest_dist >= 0.0f);
// Calc the intersection point
point = pos; // Start with position
point[closest_axis] = closest_axis_coord;
#if 0
static int print_now;
if ((print_now++ % 60) == 0)
{
Dbg_Message("Closest axis %d, (min - max) pos (%f - %f) %f, closest dist %f, closest coord %f", closest_axis,
m_min[closest_axis], m_max[closest_axis], pos[closest_axis], closest_dist, closest_axis_coord);
}
#endif
}
else
{
point[W] = 1.0f; // Homogeneous
// Go through each axis. If the pos coordinate is between the min and max, use that
// coordinate. Otherwise, use the min or max coordinate that is closest.
for (int axis = X; axis <= Z; axis++)
{
if (axes_within_flags & (1 << axis))
{
// Within, use pos coord
point[axis] = pos[axis];
}
else
{
// Figure out which end we need
if (pos[axis] <= m_min[axis])
{
point[axis] = m_min[axis];
}
else
{
point[axis] = m_max[axis];
}
}
}
}
}
}

354
Code/Core/Math/geometry.h Normal file
View File

@ -0,0 +1,354 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/geometry.h **
** **
** Created: 11/29/99 - mjb **
** **
** Description: Vector Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_GEOMETRY_H
#define __CORE_MATH_GEOMETRY_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/****************************************************************************
*
* Class: Vector
*
* Description: Vector math class
*
****************************************************************************/
class Plane;
class Line
{
friend class Plane;
public:
Line();
Line ( const Vector &start, const Vector &end );
// Line& operator+= ( const Vector& v );
inline void MirrorAboutStart();
inline void FlipDirection();
bool operator== ( const Line& l ) const;
bool operator!= ( const Line& l ) const;
Line& operator+= ( const Vector& v );
Line& operator-= ( const Vector& v );
float Length() const {return (m_end-m_start).Length();}
Vector m_start, m_end;
private:
};
class Plane
{
friend class Line;
public:
Plane();
Plane (const Vector &point, const Vector &normal);
Vector m_point, m_normal;
private:
};
class Rectangle
{
public:
Rectangle ( );
Rectangle ( const Vector& corner, const Vector& first_edge, const Vector& second_edge );
Vector m_corner, m_first_edge, m_second_edge;
private:
};
/****************************************************************************
*
* Class: CBBox
*
* Description: Axis-aligned Bounding Box
*
****************************************************************************/
class CBBox
{
public:
// Constructors
CBBox();
CBBox(const Vector &point);
CBBox(const Vector &min, const Vector &max);
//
inline void Set(const Vector &min, const Vector &max);
inline void Reset();
//
inline const Vector &GetMin() const;
inline const Vector &GetMax() const;
inline void SetMin(const Vector &min);
inline void SetMax(const Vector &max);
//
void AddPoint(const Vector &point);
inline bool Intersect(const CBBox &bbox) const;
inline bool CouldIntersect(const Vector &v0, const Vector &v1, const Vector &v2) const; // Intersect w/ triangle
inline bool Within(const Vector &point) const;
inline bool Within(const CBBox &bbox) const;
int WithinAxes(const Vector &point, uint32 &axis_flags) const; // Returns number of axes within and flags for which ones
// Checks to see if the line intersects any of the sides
bool LineIntersect( const Mth::Line &line, Mth::Vector &point, Mth::Vector &normal ) const;
// Finds the closest point on the bounding box to a position
void GetClosestIntersectPoint(const Mth::Vector &pos, Mth::Vector &point) const;
void DebugRender(uint32 rgba, int frames = 0) const;
void DebugRender(const Mth::Matrix & transform, uint32 rgba, int frames = 0) const;
private:
//
Vector m_min, m_max;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
bool LineLineIntersect( Line & l1, Line & l2, Vector *pa, Vector *pb, float *mua, float *mub, bool clamp = true );
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Line::operator== ( const Line& l ) const
{
return ( m_start == l.m_start) && ( m_end == l.m_end );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Line::operator!= ( const Line& l ) const
{
return !( *this == l );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Line& Line::operator+= ( const Vector& v )
{
m_start += v;
m_end += v;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Line& Line::operator-= ( const Vector& v )
{
m_start -= v;
m_end -= v;
return *this;
}
// A->B becomes B<-A, where A is unchanged
inline void Line::MirrorAboutStart()
{
m_end = m_start - 2.0f * ( m_end - m_start );
}
// A->B becores B->A (A and B swap positions)
inline void Line::FlipDirection()
{
Mth::Vector temp = m_end;
m_end = m_start;
m_start = temp;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CBBox::Reset()
{
// m_min = Vector( (float)HUGE_VAL, (float)HUGE_VAL, (float)HUGE_VAL);
// m_max = Vector((float)-HUGE_VAL, (float)-HUGE_VAL, (float)-HUGE_VAL);
m_min = Vector( 10000000.0f, 10000000.0f, 10000000.0f);
m_max = Vector(-10000000.0f, -10000000.0f, -10000000.0f);
}
inline void CBBox::Set(const Vector &min, const Vector &max)
{
m_min = min;
m_max = max;
}
inline const Vector &CBBox::GetMin() const
{
return m_min;
}
inline const Vector &CBBox::GetMax() const
{
return m_max;
}
inline void CBBox::SetMin(const Vector &min)
{
m_min = min;
}
inline void CBBox::SetMax(const Vector &max)
{
m_max = max;
}
// for intersection test, we do X and Z first,
// as we war aer more likely to be intersecting in the Y
// as everyhting is about the same height
// so this eliminates thigns quicker
inline bool CBBox::Intersect(const CBBox &bbox) const
{
if ((m_min[X] > bbox.m_max[X]) || (bbox.m_min[X] > m_max[X]) ||
(m_min[Z] > bbox.m_max[Z]) || (bbox.m_min[Z] > m_max[Z]) ||
(m_min[Y] > bbox.m_max[Y]) || (bbox.m_min[Y] > m_max[Y]))
{
return false;
}
return true;
}
inline bool CBBox::Within(const Vector &point) const
{
return ((point[X] >= m_min[X]) && (point[Y] >= m_min[Y]) && (point[Z] >= m_min[Z]) &&
(point[X] <= m_max[X]) && (point[Y] <= m_max[Y]) && (point[Z] <= m_max[Z]));
}
inline bool CBBox::Within(const CBBox &bbox) const
{
if ((bbox.m_min[X] >= m_min[X]) && (bbox.m_max[X] <= m_max[X]) &&
(bbox.m_min[Y] >= m_min[Y]) && (bbox.m_max[Y] <= m_max[Y]) &&
(bbox.m_min[Z] >= m_min[Z]) && (bbox.m_max[Z] <= m_max[Z]))
{
return true;
}
return false;
}
// Not So Quick & Dirty Intersection w/ Triangle
inline bool CBBox::CouldIntersect(const Vector &v0, const Vector &v1, const Vector &v2) const
{
if ( ( v0[X] > m_max[X] ) &&
( v1[X] > m_max[X] ) &&
( v2[X] > m_max[X] ) ) return false;
if ( ( v0[X] < m_min[X] ) &&
( v1[X] < m_min[X] ) &&
( v2[X] < m_min[X] ) ) return false;
if ( ( v0[Y] > m_max[Y] ) &&
( v1[Y] > m_max[Y] ) &&
( v2[Y] > m_max[Y] ) ) return false;
if ( ( v0[Y] < m_min[Y] ) &&
( v1[Y] < m_min[Y] ) &&
( v2[Y] < m_min[Y] ) ) return false;
if ( ( v0[Z] > m_max[Z] ) &&
( v1[Z] > m_max[Z] ) &&
( v2[Z] > m_max[Z] ) ) return false;
if ( ( v0[Z] < m_min[Z] ) &&
( v1[Z] < m_min[Z] ) &&
( v2[Z] < m_min[Z] ) ) return false;
return true;
}
} // namespace Mth
#endif // __CORE_MATH_GEOMETRY_H

374
Code/Core/Math/math.cpp Normal file
View File

@ -0,0 +1,374 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: math.cpp **
** **
** Created by: 11/24/99 - mjb **
** **
** Description: Math Library code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#ifdef __PLAT_WN32__
#include <math.h>
#endif
#ifdef __PLAT_XBOX__
#include <math.h>
#endif
/*****************************************************************************
** DBG Information **
*****************************************************************************/
#include <core/math/math.h>
#if DEBUGGING_REPLAY_RND
#include <sys\timer.h>
#include <string.h>
extern int *gReplayTestRndLine;
extern uint64 *gReplayTestRndFunc;
static int gRndIndex = 0;
static int gTestMode = 0;
#define MAX_RND_TEST_INDEX 3666
#endif
namespace Mth
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
static int RandSeed;
static int RandA;
static int RandB;
static int RandSeed2;
static int RandC;
static int RandD;
void InitialRand(int a)
{
RandSeed = a;
RandA = 314159265;
RandB = 178453311;
RandSeed2 = a;
RandC = 314159265;
RandD = 178453311;
}
#if DEBUGGING_REPLAY_RND
static bool gFuckedUp = false;
bool RndFuckedUp( void )
{
if ( gTestMode != 2 )
return ( false );
return ( gFuckedUp );
}
int Rnd_DbgVersion(int n, int line, char *file)
{
if ( gRndIndex < MAX_RND_TEST_INDEX )
{
if ( gTestMode == 1 )
{
// record:
gReplayTestRndLine[ gRndIndex ] = line;
strncpy( ( char * )( &gReplayTestRndFunc[ gRndIndex ] ), file, 8 );
gRndIndex++;
}
else if ( gTestMode == 2 )
{
// compare:
if ( line != gReplayTestRndLine[ gRndIndex ] )
{
char temp[ 9 ];
strncpy( temp, ( char * )( &gReplayTestRndFunc[ gRndIndex ] ), 8 );
temp[ 8 ] = '\0';
Dbg_Message( "********Rnd Fuckup!********* num %d time %d\ncurrent line %d file %s conflicts with prev line %d file %s",
Tmr::GetTime( ), gRndIndex, line, file, gReplayTestRndLine[ gRndIndex ], temp );
gFuckedUp = true;
}
else
{
gFuckedUp = false;
}
gRndIndex++;
}
}
RandSeed=RandSeed*RandA+RandB;
RandA = (RandA ^ RandSeed) + (RandSeed>>4);
RandB += (RandSeed>>3) - 0x10101010L;
return (int)((RandSeed&0xffff) * n)>>16;
}
void SetRndTestMode( int mode )
{
gTestMode = mode;
gRndIndex = 0;
}
#else
int Rnd(int n)
{
RandSeed=RandSeed*RandA+RandB;
RandA = (RandA ^ RandSeed) + (RandSeed>>4);
RandB += (RandSeed>>3) - 0x10101010L;
return (int)((RandSeed&0xffff) * n)>>16;
}
#endif
int Rnd2(int n)
{
RandSeed2=RandSeed2*RandC+RandD;
RandC = (RandC ^ RandSeed2) + (RandSeed2>>4);
RandD += (RandSeed2>>3) - 0x10101010L;
return (int)((RandSeed2&0xffff) * n)>>16;
}
// Return a random number in the range +/- n
float PlusOrMinus(float n)
{
float range = (float)(Rnd(10000));
range -= 5000.0f;
return n * range / 5000.0f;
}
#if 0
// 8192 makes Kensinf and sinf match to all 6 decimal places, (when x is in the range -2pi to 2pi)
// apart from very occassionally where there might be a .000001 difference.
// The table size must be a power of two.
#define SINF_NUM_DIVISIONS 8192
static float pSinLookup[SINF_NUM_DIVISIONS+5]; // +5 for good measure, since sometimes we look one beyond the end.
void InitSinLookupTable()
{
// The lookup table covers a whole period (0 to 2pi) of the sin function.
// This saves a few if's in the sin function.
for (int i=0; i<SINF_NUM_DIVISIONS+5; ++i)
{
pSinLookup[i]=sinf(i*2.0f*3.141592654f/SINF_NUM_DIVISIONS); // Mth::PI won't compile for some reason??
}
}
float Kensinf(float x)
{
// Get the index into the table as a floating point value. This value may be negative
// or out of bounds of the array, but don't worry about that yet.
float r=(x*(SINF_NUM_DIVISIONS/2))/3.141592654f;
// Get the integer part.
int i=(int)r;
// Make r be the fractional part, so that r is a value between 0 and 1 (or 0 and -1)
// that indicates how far we are between the two adjacent entries in the table.
r-=i;
// Make i be in range, which can be done with an integer 'and' because the table size
// is chosen to be a power of two.
// Note that this still works the way we want it to if i is negative.
// If i is a certain distance below 0, anding it will map it to that distance below the
// end of the table, which is what we want because the lookup table covers a whole
// period of the sine function.
// (Generally, -x & (n-1) is n-x when n is a power of 2, eg -3&7 = 5 = (8-3) )
i&=(SINF_NUM_DIVISIONS-1);
float *pPoo=pSinLookup+i;
// Hmmm, the following is technically wrong, it should be -- not ++ for when x is negative.
// However, always using ++ does not appear to affect the accuracy at all, so there's no need to fix it!
// Doing a -- for when x is negative would mean having to do another if, and yet another to
// check in case pPoo points to the first element, yuk.
// Using ++ even when x is negative works because the gradient does not change
// much between points. When x is negative, r will be negative, and using the next gradient
// to move back gives roughly the same answer as using the previous gradient. Wahay!!
float a=*pPoo++;
float b=*pPoo;
return a+(b-a)*r;
}
float Kencosf(float x)
{
float r=(x*(SINF_NUM_DIVISIONS/2))/3.141592654f;
int i=(int)r;
r-=i;
// This is the only difference from Kensinf.
i+=(SINF_NUM_DIVISIONS/4); // Add a quarter period.
i&=(SINF_NUM_DIVISIONS-1);
float *pPoo=pSinLookup+i;
float a=*pPoo++;
float b=*pPoo;
return a+(b-a)*r;
/*
float sqr = x*x;
float result = 0.03705f;
result *= sqr;
result -= 0.4967;
result *= sqr;
result += 1.0f;
return result;
*/
}
#endif
float Kenacosf(float x)
{
// Got this formula off the internet, forgot where though ...
if (x<0.0f)
{
x=-x;
float root = sqrtf(1.0f-x);
float result = -0.0187293f;
result *= x;
result += 0.0742610f;
result *= x;
result -= 0.2121144f;
result *= x;
result += 1.5707288f;
result *= root;
return 3.141592654f-result;
}
else
{
float root = sqrtf(1.0f-x);
float result = -0.0187293f;
result *= x;
result += 0.0742610f;
result *= x;
result -= 0.2121144f;
result *= x;
result += 1.5707288f;
result *= root;
return result;
}
}
float FRunFilter( float target, float current, float delta )
{
if ( target < current )
{
if ( ( current - target ) > fabsf( delta ) )
{
return ( current - fabsf( delta ) );
}
return ( target );
}
if ( ( target - current ) > fabsf( delta ) )
{
return ( current + fabsf( delta ) );
}
return ( target );
}
int RunFilter( int target, int current, int delta )
{
if ( target < current )
{
if ( current - target > abs( delta ) )
return ( target );
return ( current - abs( delta ) );
}
if ( target - current > abs( delta ) )
return ( target );
return ( current + abs( delta ) );
}
// returns atan(y/x) with appropiate sign determinations
// although it does not work, as we cant; find atan .....
/*
float Atan2 (float y, float x)
{
if (x == 0.0f)
{
if (y < 0.0f) return(-PI/2.0f);
else return( PI/2.0f);
}
else
{
if (x < 0.0f) {
if (y < 0.0f)
return(atan(y/x)-PI);
else
return(atan(y/x)+PI);
}
else
{
return(atan(y/x));
}
}
}
*/
} // namespace Mth

473
Code/Core/Math/math.h Normal file
View File

@ -0,0 +1,473 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/math.h **
** **
** Created: 11/23/99 - mjb **
** **
** Description: Math Library **
** **
*****************************************************************************/
#ifndef __CORE_MATH_MATH_H
#define __CORE_MATH_MATH_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifdef __PLAT_XBOX__
#include <math.h> // Required for fabsf().
#include <core\math\xbox\sse.h>
#endif
#ifdef __PLAT_WN32__
#include <math.h> // Required for fabsf().
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __USER_MATT__
#define DEBUGGING_REPLAY_RND 0
#else
#define DEBUGGING_REPLAY_RND 0
#endif
#if DEBUGGING_REPLAY_RND
#define Rnd( x ) Rnd_DbgVersion( ( x ), __LINE__, __FILE__ )
#else
#define Rnd( x ) Rnd( x )
#endif
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Type Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
void InitialRand(int a);
#if DEBUGGING_REPLAY_RND
int Rnd_DbgVersion(int n, int line, char *file);
void SetRndTestMode( int mode );
bool RndFuckedUp( void );
#else
int Rnd(int n);
#endif
// use for non-deterministic things
// especially for CD-timing reliant stuff that would throw off our random number dealy whopper.
int Rnd2(int n);
float PlusOrMinus(float n);
void InitSinLookupTable();
float Kensinf(float x);
float Kencosf(float x);
float Kenacosf(float x);
float Atan2 (float y, float x); // replaces atan2, much faster
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline int Abs ( int x )
{
return ( x>=0?x:-x);
}
inline float Abs ( float x )
{
return float ( fabsf ( x ));
}
// round down to nearest whole number
inline float Whole ( float x )
{
return (float) ( (int) ( x ));
}
// round to nearest whole number
inline float Round ( float x )
{
return (float) ( (int) ( x + 0.499999f));
}
//////////////////////////////////////////////////////////////////////////////////////////
// Calculate the "Parabolic Lerp" value for a set of parameters
// (Note: made-up name, by Mick)
//
// A lerp (Linear intERPalotion) value is always in the range 0.0 to 1.0
// and is used to move one value (A) towards another (B)
// usually the lerp value is fixed.
//
// A new value C is calculated as C = A + lerp * (B - A)
//
// a "ParaLerp" is a lerp value that varies based on the distance apart of the two values
//
// The purpose of this function is to be able to smoothly change a value
// that really only needs lerping when the values are within a small range
// The result of this equation is a parabolic curve that quickly tends
// towards lerp = 1.0, as x increases
// The valeu "Rate" is the value of x for which lerp half way between Min and 1.0
// Min is the value of lerp when x is 0
inline float ParaLerp(float x, float Rate = 1.0f, float Minimum = 0.0f)
{
float lerp = Minimum + (1 - 1 / (1 + x / Rate) ) * (1 - Minimum);
return lerp;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float ClampMin ( float v, float min )
{
if ( v < min )
{
return min;
}
else
{
return v;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float ClampMax ( float v, float max )
{
if ( v > max )
{
return max;
}
else
{
return v;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Clamp ( float v, float min, float max )
{
return ClampMin ( ClampMax ( v, max ), min );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Lerp ( float a, float b, float value )
{
return a + ( b - a ) * value;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float LinearMap ( float a, float b, float value, float value_min, float value_max )
{
return Lerp(a, b, (value - value_min) / (value_max - value_min));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothStep ( float value )
{
// interpolates from zero to one with a zero derivative at the end-points
return -2.0f * value * value * ( value - (3.0f / 2.0f) );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothInterp ( float a, float b, float value )
{
return Lerp(a, b, SmoothStep(value));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float SmoothMap ( float a, float b, float value, float value_min, float value_max )
{
return Lerp(a, b, SmoothStep((value - value_min) / (value_max - value_min)));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Max ( float a, float b )
{
return ( a > b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Min ( float a, float b )
{
return ( a < b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Sgn ( float x )
{
if ( x < 0.f )
{
return -1.0f;
}
else
{
return 1.0f;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Sqr ( float x )
{
return ( x * x );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Swap ( float& a, float& b )
{
float t = a;
a = b;
b = t;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Equal ( const float a, const float b, const float perc )
{
return ( Abs ( a - b ) <= (( Abs ( a ) + Abs ( b )) * perc ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline sint Max ( sint a, sint b )
{
return ( a > b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline sint Min ( sint a, sint b )
{
return ( a < b ) ? a : b;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Max3 ( float a, float b, float c )
{
return Max(a, Max(b,c));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Min3 ( float a, float b, float c )
{
return Min(a, Min(b,c));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Determinant ( float a, float b, float c, float d )
{
return ( a * d ) - ( b * c );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Determinant3 ( float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3 )
{
return a1 * (b2 * c3 - b3 * c2) -
b1 * (a2 * c3 - a3 * c2) +
c1 * (a2 * b3 - a3 * b2);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline int WeightedRnd ( float min_val, float max_val )
{
// This random function uses the West distribution
// to return values that favor the midpoint.
// For example, WeightedRnd( 10, 20 ) returns:
// Bucket[10] = 2.12 percent
// Bucket[11] = 5.72 percent
// Bucket[12] = 9.44 percent
// Bucket[13] = 13.87 percent
// Bucket[14] = 18.16 percent
// Bucket[15] = 15.70 percent
// Bucket[16] = 14.52 percent
// Bucket[17] = 10.16 percent
// Bucket[18] = 6.05 percent
// Bucket[19] = 2.26 percent
// Bucket[20] = 2.00 percent
float range = ( max_val - min_val ) / 2;
float midpoint = min_val + range;
float random_val = range - (float)sqrtf((float)Rnd( (int)(range * range) ) );
// negate it half of the time
if ( Rnd(2) )
{
random_val = -random_val;
}
return (int)( random_val + midpoint );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Trig
const float EPSILON = 0.000001f;
const float PI = 3.141592654f;
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float DegToRad ( float degrees )
{
return degrees * ( PI / 180.0f);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float RadToDeg ( float radians )
{
return radians * ( 180.0f / PI );
}
int RunFilter( int target, int current, int delta );
float FRunFilter( float target, float current, float delta );
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Mth
#endif // __CORE_MATH_MATH_H

1049
Code/Core/Math/matrix.cpp Normal file

File diff suppressed because it is too large Load Diff

191
Code/Core/Math/matrix.h Normal file
View File

@ -0,0 +1,191 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/Matrix.h **
** **
** Created: 11/29/99 - mjb **
** **
** Description: 4x4 Matrix Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_MATRIX_H
#define __CORE_MATH_MATRIX_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Mth
{
enum
{
RIGHT, UP, AT, POS
};
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/****************************************************************************
*
* Class: Matrix
*
* Description: 4x4 Matrix math class
*
****************************************************************************/
class Matrix
{
public:
Matrix ( void );
Matrix ( const Matrix& src );
Matrix ( const Vector& axis, const float angle );
Matrix ( int axis, const float angle );
Matrix ( float p, float h, float r ); // Euler to Matrix
Matrix ( const Mth::Quat& orientaion );
Matrix& operator= ( const Matrix& src );
Matrix& operator+= ( const Matrix& n );
Matrix& operator*= ( const Matrix& n );
Matrix& operator*= ( const float f );
bool operator== ( const Matrix& n ) const;
bool operator!= ( const Matrix& n ) const;
float Determinant ( void ) const;
bool IsIdent ( void ) const;
Matrix& Ident ( void ); // set to 4x4 identity
Matrix& Identity ( void ); // same, but better name
Matrix& Zero ( void ); // set to all 0's
Matrix& Adjoint ( const Matrix& src );
Matrix& Invert ( const Matrix& src ); // this = Invert ( src )
Matrix& Invert ( void ); // this = Invert ( this )
Matrix& InvertUniform ( void );
Matrix& Transpose ( const Matrix& src );
Matrix& Transpose ( void );
Vector Transform ( const Vector& src ) const;
Vector TransformAsPos ( const Vector& src ) const;
Vector Rotate ( const Vector& src ) const;
Matrix& OrthoNormalize ( const Matrix& src ); // this = OrthoNornalize ( src )
Matrix& OrthoNormalize ( void ); // this = OrthoNormalize ( this )
void RotateLocal ( const Vector& src );
Matrix& Translate ( const Vector& trans );
Matrix& TranslateLocal ( const Vector& trans );
Matrix& Rotate ( const Vector& axis, const float angle );
Matrix& RotateLocal ( const Vector& axis, const float angle );
Matrix& RotateLocal ( int axis, float angle );
Matrix& RotateX ( const float angle );
Matrix& RotateXLocal ( const float angle );
Matrix& RotateY ( const float angle );
Matrix& RotateYLocal ( const float angle );
Matrix& RotateZ ( const float angle );
Matrix& RotateZLocal ( const float angle );
Matrix& Scale ( const Vector& scale );
Matrix& ScaleLocal ( const Vector& scale );
Vector& GetRight ( void ) { return *(Vector*)(&row[RIGHT]); }
Vector& GetUp ( void ) { return *(Vector*)(&row[UP]); }
Vector& GetAt ( void ) { return *(Vector*)(&row[AT]); }
Vector& GetPos ( void ) { return *(Vector*)(&row[POS]); }
void SetPos ( const Vector& trans );
Matrix& SetColumn ( sint i, const Vector& v );
Vector GetColumn ( sint i ) const;
const Vector& operator[] ( sint i ) const;
Vector& operator[] ( sint i );
Matrix& OrthoNormalizeAbout(int r0);
void PrintContents() const;
void GetEulers( Vector& euler ) const;
void GetRotationAxisAndAngle( Vector* pAxis, float* pRadians );
bool PatchOrthogonality ( );
Matrix& SetFromAngles ( const Vector& angles );
private:
enum
{
NUM_ELEMENTS = 4
};
// Vector row[NUM_ELEMENTS]; // Old style, an array of vectors
float row[NUM_ELEMENTS][4]; // New style, an array of float, for constructor optimization
} nAlign(128);
/*****************************************************************************
** Private Inline Functions **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
#ifdef __PLAT_NGPS__
void xsceVu0MulMatrix(Mth::Matrix* m0, Mth::Matrix* m1, const Mth::Matrix* m2);
#endif
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
void Swap ( Matrix& a, Matrix& b );
void Slerp ( Matrix& result, const Matrix& s1, const Matrix& s2, float t );
Matrix operator* ( const Matrix& m1, const Matrix& m2 );
ostream& operator<< ( ostream& os, const Matrix& m );
Matrix& CreateRotateMatrix ( Matrix& mat, const Vector& axis, const float angle );
Matrix& CreateRotateMatrix ( Matrix& mat, int axis, const float angle );
Matrix& CreateRotateXMatrix ( Matrix& mat, const float angle );
Matrix& CreateRotateYMatrix ( Matrix& mat, const float angle );
Matrix& CreateRotateZMatrix ( Matrix& mat, const float angle );
Matrix& CreateFromToMatrix( Matrix &mtx, Vector from, Vector to );
Matrix& CreateMatrixLookAt( Matrix& mat, const Vector& pos, const Vector& lookat, const Vector& up );
Matrix& CreateMatrixOrtho( Matrix& mat, float width, float height, float f_near, float f_far );
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Mth
#endif // __CORE_MATH_MATRIX_H

1053
Code/Core/Math/matrix.inl Normal file

File diff suppressed because it is too large Load Diff

143
Code/Core/Math/quat.h Normal file
View File

@ -0,0 +1,143 @@
/*****************************************************************************
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/Quat.h **
** **
** Created: 11/23/99 - mjb **
** **
** Description: Quaternion Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_QUAT_H
#define __CORE_MATH_QUAT_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math/vector.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class Matrix; // forward declaration
/****************************************************************************
*
* Class: Quat
*
* Description: Quaternion math class
*
****************************************************************************/
class Quat //: public Spt::Class
{
public:
friend bool quat_equal ( const Quat& q1, const Quat& q2, const float tol );
Quat ( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f );
Quat ( const Vector& axis, float angle );
Quat ( const Matrix& mat );
Quat& Invert ( void );
Quat& Invert ( const Quat& src );
float Modulus ( void );
float ModulusSqr ( void ) const;
Quat& Normalize ( float len = 1.0f );
Vector Rotate ( const Vector& vec ) const;
void SetScalar ( const float w );
void SetVector ( const float x, const float y, const float z );
void SetVector ( const Vector& v );
const float& GetScalar ( void ) const;
const Vector& GetVector ( void ) const { return quat; }
void GetMatrix ( Matrix& mat ) const;
Quat& operator= ( const Quat& q );
Quat& operator+= ( const Quat& q );
Quat& operator-= ( const Quat& q );
Quat& operator*= ( const Quat& q );
Quat& operator*= ( float s );
Quat& operator/= ( float s );
const float& operator[] ( sint i ) const;
float& operator[] ( sint i );
private:
Vector quat; // X,Y,Z : Imaginary (Vector) component
// W : Real (Scalar) component
};
/*****************************************************************************
** Private Inline Functions **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
Quat operator+ ( const Quat& q1, const Quat& q2 );
Quat operator- ( const Quat& q1, const Quat& q2 );
Quat operator* ( const Quat& q1, const Quat& q2 );
Quat operator* ( const Quat& q, const float s );
Quat operator* ( const float s, const Quat& q );
Quat operator- ( const Quat& q ); // negate all elements -> equilavent rotation
float DotProduct ( const Quat& v1, const Quat& v2 );
Quat Slerp ( const Quat& q1, const Quat& q2, const float t );
Quat FastSlerp( Quat& qIn1, Quat& qIn2, const float t );
bool Equal ( const Quat& q1, const Quat& q2, const float tol = 0.0001f );
ostream& operator<< ( ostream& os, const Quat& v );
Quat EulerToQuat( const Vector& v );
// converts a quat+vector xform into a matrix xform
void QuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix );
void SCacheQuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix );
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Mth
#endif // __CORE_MATH_QUAT_H

815
Code/Core/Math/quat.inl Normal file
View File

@ -0,0 +1,815 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (Mth) **
** **
** File name: core/math/Quat.inl **
** **
** Created: 11/23/99 - mjb **
** **
** Description: Quaternion Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_QUAT_INL
#define __CORE_MATH_QUAT_INL
namespace Mth
{
/******************************************************************/
/* */
/* */
/******************************************************************/
inline const float& Quat::operator[] ( sint i ) const
{
return quat[i];
}
/*****************************************************************************
** Private Inline Functions **
*****************************************************************************/
inline bool quat_equal( const Quat& q1, const Quat& q2, const float tol )
{
return ( Equal( q1.quat, q2.quat, tol ));
}
/*****************************************************************************
** Public Inline Functions **
*****************************************************************************/
inline Quat::Quat( float cx, float cy, float cz, float cw )
: quat( cx, cy, cz, cw )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat::Quat( const Vector& axis, float angle )
{
float mod = axis.Length();
float ang = angle / 2.0f;
mod = ( mod > 0.0f ) ? ( 1.0f / mod ) : 0.0f;
mod *= sinf( ang );
SetVector( mod * axis[X], mod * axis[Y], mod * axis[Z] );
SetScalar( cosf ( ang ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float& Quat::operator[] ( sint i )
{
return quat[i];
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat::Quat( const Matrix& m )
{
float t = m[X][X] + m[Y][Y] + m[Z][Z];
float trace;
if ( t > 0.0f )
{
trace = sqrtf( t + 1.0f );
SetScalar( trace * 0.5f );
trace = 0.5f / trace;
SetVector(( m[Z][Y] - m[Y][Z] ) * trace,
( m[X][Z] - m[Z][X] ) * trace,
( m[Y][X] - m[X][Y] ) * trace );
}
else
{
// find greatest element in Matrix diagonal
sint i = X;
if ( m[Y][Y] > m[X][X] ) i = Y;
if ( m[Z][Z] > m[i][i] ) i = Z;
sint j = ( i + 1 ) % W;
sint k = ( j + 1 ) % W;
trace = sqrtf(( m[i][i] - (m[j][j] + m[k][k] )) + 1.0f );
quat[i] = ( trace * 0.5f );
trace = 0.5f / trace;
quat[j] = ( m[j][i] + m[i][j] ) * trace;
quat[k] = ( m[k][i] + m[i][k] ) * trace;
quat[W] = ( m[k][j] - m[j][k] ) * trace;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::Invert( void ) // this = Invert ( this )
{
quat.Negate();
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::Invert( const Quat& src ) // this = Invert ( src )
{
quat.Negate( src.quat );
quat[W] = src.quat[W];
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Quat::Modulus( void )
{
return sqrtf( ModulusSqr () );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float Quat::ModulusSqr ( void ) const
{
return (( quat[X] * quat[X] ) +
( quat[Y] * quat[Y] ) +
( quat[Z] * quat[Z] ) +
( quat[W] * quat[W] ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::Normalize( float len )
{
float mod = Modulus();
if ( mod > 0.0f )
{
mod = len / mod;
quat *= mod;
}
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Vector Quat::Rotate( const Vector& vec ) const
{
Quat inv;
// Quat pt( vec[X], vec[Y], vec[Z], vec[W] );
Quat pt( vec[X], vec[Y], vec[Z], 1.0f ); // Mick: Setting W to sensible value, otherwise can cause overflow
Quat res = *this;
inv.Invert( *this );
res *= pt;
res *= inv;
return Vector( res[X], res[Y], res[Z], res[W] );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Quat::SetScalar( const float w )
{
quat[W] = w;
};
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Quat::SetVector( const float x, const float y, const float z )
{
quat[X] = x;
quat[Y] = y;
quat[Z] = z;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Quat::SetVector( const Vector& v )
{
quat[X] = v[X];
quat[Y] = v[Y];
quat[Z] = v[Z];
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator= ( const Quat& q )
{
quat = q.quat;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator+= ( const Quat& q )
{
quat += q.quat;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator-= ( const Quat& q )
{
quat -= q.quat;
return *this;
}
inline const float& Quat::GetScalar ( void ) const
{
return quat[W];
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator*= ( const Quat& q )
{
float s1 = GetScalar();
float s2 = q.GetScalar();
Vector v1 = GetVector();
Vector v2 = q.GetVector();
SetVector (( v2 * s1 ) + ( v1 * s2 ) + CrossProduct ( v1, v2 ));
SetScalar (( s1 * s2 ) - DotProduct ( v1, v2 ));
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator*= ( float s )
{
quat *= s;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat& Quat::operator/= ( float s )
{
quat /= s;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Quat::GetMatrix ( Matrix& mat ) const
{
float xs, ys, zs,
wx, wy, wz,
xx, xy, xz,
yy, yz, zz, ss;
#if 0
// our original version. Seems essentially broken, as LengthSqr ignores W
ss = 2.0f / quat.LengthSqr();
#else
// version suggested by Andre at Left Field
// uses proper Modulus, and clamps 2.0/0.0f to zero
ss = ModulusSqr();
ss = ( ss>0.0f ? 2.0f/ss : 0.0f);
#endif
xs = quat[X] * ss;
ys = quat[Y] * ss;
zs = quat[Z] * ss;
wx = quat[W] * xs;
wy = quat[W] * ys;
wz = quat[W] * zs;
xx = quat[X] * xs;
xy = quat[X] * ys;
xz = quat[X] * zs;
yy = quat[Y] * ys;
yz = quat[Y] * zs;
zz = quat[Z] * zs;
mat[X][X] = 1.0f - (yy + zz);
mat[Y][X] = xy + wz;
mat[Z][X] = xz - wy;
mat[X][Y] = xy - wz;
mat[Y][Y] = 1.0f - (xx + zz);
mat[Z][Y] = yz + wx;
mat[X][Z] = xz + wy;
mat[Y][Z] = yz - wx;
mat[Z][Z] = 1.0f - (xx + yy );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator+ ( const Quat& q1, const Quat& q2 )
{
Quat sum = q1;
sum += q2;
return sum;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator- ( const Quat& q1, const Quat& q2 )
{
Quat diff = q1;
diff -= q2;
return diff;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator* ( const Quat& q1, const Quat& q2 )
{
Quat prod = q1;
prod *= q2;
return prod;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator* ( const Quat& q, const float s )
{
Quat prod = q;
prod *= s;
return prod;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator* ( const float s, const Quat& q )
{
return q * s;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat operator- ( const Quat& q )
{
return Quat ( -q[X], -q[Y], -q[Z], -q[W] );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float DotProduct ( const Quat& v1, const Quat& v2 )
{
return ( v1[X] * v2[X] ) + ( v1[Y] * v2[Y] ) + ( v1[Z] * v2[Z] ) + ( v1[W] * v2[W] );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Quat Slerp ( const Quat& q1, const Quat& q3, float t )
{
float sclp, sclq;
// GJ: Need to possibly negate the second quaternion,
// to avoid spinning in the wrong direction.
Quat q2 = q3;
if ( DotProduct( q1, q3 ) < 0.0f )
{
q2 = -q2;
}
float coso = q1.GetScalar() * q2.GetScalar() +
DotProduct ( q1.GetVector(), q2.GetVector());
Quat q;
if (( 1.0f + coso + 1.0f ) > EPSILON )
{
if (( 1.0f - coso ) > EPSILON ) // slerp
{
float omega = acosf ( coso );
float sino = sinf ( omega );
sclp = sinf (( 1.0f - t ) * omega ) / sino;
sclq = sinf ( t * omega ) / sino;
}
else // lerp ( angle tends to 0 )
{
sclp = 1.0f - t;
sclq = t;
}
q = ( sclp * q1 ) + ( sclq * q2 );
}
else // angle tends to 2*PI
{
q.SetVector ( -q1[Y], q1[X], -q1[W] );
q.SetScalar ( q1[Z] );
sclp = sinf (( 1.0f - t ) * PI / 2.0f );
sclq = sinf ( t * PI / 2.0f );
q.SetVector (( sclp * q1.GetVector()) + ( sclq * q.GetVector()));
}
return q;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Equal ( const Quat& q1, const Quat& q2, const float tol )
{
if (( quat_equal ( q1, q2, tol )) ||
( quat_equal ( -q1, q2, tol )))
{
return true;
}
return false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline ostream& operator<< ( ostream& os, const Quat& q )
{
return os << "(( " << q[X] << ", " << q[Y] << ", " << q[Z] << ") , " << q[W] << " )";
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void QuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix )
{
Dbg_Assert( pQ );
Dbg_Assert( pT );
Dbg_Assert( pMatrix );
pQ->Invert();
Mth::Vector square;
Mth::Vector cross;
Mth::Vector wimag;
square[X] = (*pQ)[X] * (*pQ)[X];
square[Y] = (*pQ)[Y] * (*pQ)[Y];
square[Z] = (*pQ)[Z] * (*pQ)[Z];
cross[X] = (*pQ)[Y] * (*pQ)[Z];
cross[Y] = (*pQ)[Z] * (*pQ)[X];
cross[Z] = (*pQ)[X] * (*pQ)[Y];
wimag[X] = (*pQ)[W] * (*pQ)[X];
wimag[Y] = (*pQ)[W] * (*pQ)[Y];
wimag[Z] = (*pQ)[W] * (*pQ)[Z];
(*pMatrix)[Mth::RIGHT][X] = 1 - 2 * (square[Y] + square[Z]);
(*pMatrix)[Mth::RIGHT][Y] = 2 * (cross[Z] + wimag[Z]);
(*pMatrix)[Mth::RIGHT][Z] = 2 * (cross[Y] - wimag[Y]);
(*pMatrix)[Mth::RIGHT][W] = 0.0f;
(*pMatrix)[Mth::UP][X] = 2 * (cross[Z] - wimag[Z]);
(*pMatrix)[Mth::UP][Y] = 1 - 2 * (square[X] + square[Z]);
(*pMatrix)[Mth::UP][Z] = 2 * (cross[X] + wimag[X]);
(*pMatrix)[Mth::UP][W] = 0.0f;
(*pMatrix)[Mth::AT][X] = 2 * (cross[Y] + wimag[Y]);
(*pMatrix)[Mth::AT][Y] = 2 * (cross[X] - wimag[X]);
(*pMatrix)[Mth::AT][Z] = 1 - 2 * (square[X] + square[Y]);
(*pMatrix)[Mth::AT][W] = 0.0f;
(*pMatrix)[Mth::POS] = *pT;
(*pMatrix)[Mth::POS][W] = 1.0f;
}
inline void SCacheQuatVecToMatrix( Mth::Quat* pQ, Mth::Vector* pT, Mth::Matrix* pMatrix )
{
Dbg_Assert( pQ );
Dbg_Assert( pT );
Dbg_Assert( pMatrix );
pQ->Invert();
Mth::Vector *p_square = ((Mth::Vector*)0x7000000)+0;
Mth::Vector *p_cross = ((Mth::Vector*)0x7000000)+1;
Mth::Vector *p_wimag = ((Mth::Vector*)0x7000000)+2;
(*p_square)[X] = (*pQ)[X] * (*pQ)[X];
(*p_square)[Y] = (*pQ)[Y] * (*pQ)[Y];
(*p_square)[Z] = (*pQ)[Z] * (*pQ)[Z];
(*p_cross)[X] = (*pQ)[Y] * (*pQ)[Z];
(*p_cross)[Y] = (*pQ)[Z] * (*pQ)[X];
(*p_cross)[Z] = (*pQ)[X] * (*pQ)[Y];
(*p_wimag)[X] = (*pQ)[W] * (*pQ)[X];
(*p_wimag)[Y] = (*pQ)[W] * (*pQ)[Y];
(*p_wimag)[Z] = (*pQ)[W] * (*pQ)[Z];
(*pMatrix)[Mth::RIGHT][X] = 1 - 2 * ((*p_square)[Y] + (*p_square)[Z]);
(*pMatrix)[Mth::RIGHT][Y] = 2 * ((*p_cross)[Z] + (*p_wimag)[Z]);
(*pMatrix)[Mth::RIGHT][Z] = 2 * ((*p_cross)[Y] - (*p_wimag)[Y]);
(*pMatrix)[Mth::RIGHT][W] = 0.0f;
(*pMatrix)[Mth::UP][X] = 2 * ((*p_cross)[Z] - (*p_wimag)[Z]);
(*pMatrix)[Mth::UP][Y] = 1 - 2 * ((*p_square)[X] + (*p_square)[Z]);
(*pMatrix)[Mth::UP][Z] = 2 * ((*p_cross)[X] + (*p_wimag)[X]);
(*pMatrix)[Mth::UP][W] = 0.0f;
(*pMatrix)[Mth::AT][X] = 2 * ((*p_cross)[Y] + (*p_wimag)[Y]);
(*pMatrix)[Mth::AT][Y] = 2 * ((*p_cross)[X] - (*p_wimag)[X]);
(*pMatrix)[Mth::AT][Z] = 1 - 2 * ((*p_square)[X] + (*p_square)[Y]);
(*pMatrix)[Mth::AT][W] = 0.0f;
(*pMatrix)[Mth::POS] = *pT;
(*pMatrix)[Mth::POS][W] = 1.0f;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Slerp ( Matrix& result, const Matrix& s1, const Matrix& s2, float t )
{
Slerp ( Quat(s1), Quat(s2), t).GetMatrix ( result );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline float counter_warp(float t, float cos_alpha)
{
const float ATTENUATION = 0.82279687f;
const float WORST_CASE_SLOPE = 0.58549219f;
float factor = 1.0f - ATTENUATION * cos_alpha;
factor *= factor;
float k = WORST_CASE_SLOPE * factor;
return t*(k*t*(2.0f*t - 3.0f) + 1.0f + k);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Mth::Quat FastSlerp( Mth::Quat& qIn1, Mth::Quat& qIn2, const float t )
{
if ( Mth::DotProduct( qIn1, qIn2 ) < 0.0f )
{
qIn2 = -qIn2;
}
# if 0
float cos_a = v1[X]*v2[X] + v1[Y]*v2[Y] + v1[Z]*v2[Z] + v1[W]*v2[W];
if (t <= 0.5f)
{
t = counter_warp(t, cos_a);
}
else
{
t = 1.0f - counter_warp(1.0f - t, cos_a);
}
# endif
float xxx_x = qIn1[X] + ( qIn2[X] - qIn1[X] ) * t;
float xxx_y = qIn1[Y] + ( qIn2[Y] - qIn1[Y] ) * t;
float xxx_z = qIn1[Z] + ( qIn2[Z] - qIn1[Z] ) * t;
float xxx_w = qIn1[W] + ( qIn2[W] - qIn1[W] ) * t;
float len = 1.0f / sqrtf( xxx_x * xxx_x + xxx_y * xxx_y + xxx_z * xxx_z + xxx_w * xxx_w );
qIn2.SetVector( xxx_x * len, xxx_y * len, xxx_z * len );
qIn2.SetScalar( xxx_w * len );
return qIn2;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Mth::Quat EulerToQuat( const Mth::Vector& euler )
{
// This code is a modified version of Left Field's
// MakeQuatFromEuler() function.
Mth::Quat q;
float roll = euler[X];
float pitch = euler[Y];
float yaw = euler[Z];
float cyaw, cpitch, croll, syaw, spitch, sroll;
float cyawcpitch, syawspitch, cyawspitch, syawcpitch;
cyaw = cosf(0.5f * yaw);
cpitch = cosf(0.5f * pitch);
croll = cosf(0.5f * roll);
syaw = sinf(0.5f * yaw);
spitch = sinf(0.5f * pitch);
sroll = sinf(0.5f * roll);
cyawcpitch = cyaw * cpitch;
syawspitch = syaw * spitch;
cyawspitch = cyaw * spitch;
syawcpitch = syaw * cpitch;
q[W] = cyawcpitch * croll + syawspitch * sroll;
q[X] = cyawcpitch * sroll - syawspitch * croll;
q[Y] = cyawspitch * croll + syawcpitch * sroll;
q[Z] = syawcpitch * croll - cyawspitch * sroll;
return q;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Mth
#endif // __CORE_MATH_QUAT_INL

235
Code/Core/Math/rect.h Normal file
View File

@ -0,0 +1,235 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/Rect.h **
** **
** Created: 01/31/00 - mjb **
** **
** Description: Math Library Rectangle class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_RECT_H
#define __CORE_MATH_RECT_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
nTemplateBaseClass ( _T, _Rect )
{
public:
_Rect ( const _T x, const _T y, const _T w, const _T h );
~_Rect ( );
void SetOriginX ( const _T ) ;
void SetOriginY ( const _T ) ;
void SetWidth ( const _T ) ;
void SetHeight ( const _T ) ;
const _T GetOriginX ( void ) const;
const _T GetOriginY ( void ) const;
const _T GetWidth ( void ) const;
const _T GetHeight ( void ) const;
private:
_T x, y, w, h;
};
/*****************************************************************************
** Type Definitions **
*****************************************************************************/
typedef _Rect < float > Rect;
typedef _Rect < sint > IRect;
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template < class _T > inline
_Rect< _T >::_Rect ( const _T _x, const _T _y, const _T _w, const _T _h )
: x (_x), y (_y), w(_w), h(_h)
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_Rect< _T >::~_Rect ( void )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void _Rect< _T >::SetOriginX ( const _T xval )
{
x = xval;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void _Rect< _T >::SetOriginY ( const _T yval )
{
y = yval;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void _Rect< _T >::SetWidth ( const _T width )
{
w = width;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void _Rect< _T >::SetHeight ( const _T height )
{
h = height;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
const _T _Rect< _T >::GetOriginX ( void ) const
{
return x;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
const _T _Rect< _T >::GetOriginY ( void ) const
{
return y;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
const _T _Rect< _T >::GetWidth ( void ) const
{
return w;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
const _T _Rect< _T >::GetHeight ( void ) const
{
return h;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
ostream& operator<< ( ostream& str, const _Rect< _T >& r )
{
str << "(( " << r.GetOriginX() << ", " << r.GetOriginY() << " ),( "
<< r.GetWidth() << ", " << r.GetHeight() << " ))";
return str;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Mth
#endif // __CORE_MATH_RECT_H

105
Code/Core/Math/rot90.cpp Normal file
View File

@ -0,0 +1,105 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/rot90.cpp **
** **
** Created: 07/17/02 - grj **
** **
** Description: Rotation 90 Math Class **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math.h>
#include <core/math/rot90.h>
namespace Mth
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** DBG Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
void RotateY90( ERot90 angle, int32& x, int32& y, int32& z )
{
int32 temp;
switch (angle)
{
case ROT_0:
break;
case ROT_90:
temp = x;
x = z;
z = -temp;
break;
case ROT_180:
x = -x;
z = -z;
break;
case ROT_270:
temp = x;
x = -z;
z = temp;
break;
default:
Dbg_MsgAssert(0, ("RotateY90() out of range: %d", angle));
break;
}
}
} // namespace Mth

26
Code/Core/Math/rot90.h Normal file
View File

@ -0,0 +1,26 @@
///////////////////////////////////////////////////////////////////////////////////////
// rot90.h
//
#ifndef __CORE_ROT90_H
#define __CORE_ROT90_H
namespace Mth
{
// Rotation values for 90 degree increment Rotation (uses no multiplication)
enum ERot90 {
ROT_0 = 0,
ROT_90,
ROT_180,
ROT_270,
NUM_ROTS
};
// Integer rotate
void RotateY90( ERot90 angle, int32& x, int32& y, int32& z );
}
#endif

274
Code/Core/Math/slerp.cpp Normal file
View File

@ -0,0 +1,274 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/slerp.cpp **
** **
** Created: 12/20/01 - gj **
** **
** Description: Slerp Interpolator Math Class **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math.h>
#include <core/math/slerp.h>
namespace Mth
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
const float USE_LERP_INSTEAD_DEGREES = 2.0f;
const float USE_LERP_INSTEAD_RADIANS = USE_LERP_INSTEAD_DEGREES * PI / 180.0f;
/*****************************************************************************
** DBG Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
SlerpInterpolator::SlerpInterpolator()
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
SlerpInterpolator::SlerpInterpolator( const Matrix * start, const Matrix * end )
{
setMatrices( start, end );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void SlerpInterpolator::setMatrices( const Matrix * start, const Matrix * end )
{
Matrix inv;
m_start = *start;
m_end = *end;
// Calculate the inverse transformation.
inv = m_start;
inv.Invert();
inv = inv * m_end;
// Get the axis and angle.
inv.GetRotationAxisAndAngle( &m_axis, &m_radians );
#if 0
// Debugging stuff
static int print_x_times = 50;
if ( print_x_times > 0 )
{
print_x_times--;
printf("Start mat\n");
m_start.PrintContents();
printf("Inv mat\n");
inv.PrintContents();
printf("End mat\n");
m_end.PrintContents();
printf("Start * Inv mat\n");
Mth::Matrix siMat = m_start;
siMat = siMat * inv;
siMat.PrintContents();
{
printf("Rotated mat w=0\n");
Mth::Matrix tempMatrix = m_start;
m_axis[W] = 0.0f;
tempMatrix.Rotate( m_axis, m_radians );
tempMatrix.PrintContents();
}
{
printf("Rotated mat w=1\n");
Mth::Matrix tempMatrix2 = m_start;
m_axis[W] = 1.0f;
tempMatrix2.Rotate( m_axis, m_radians );
tempMatrix2.PrintContents();
}
{
printf("Rotated local mat w=0\n");
Mth::Matrix tempMatrix = m_start;
m_axis[W] = 0.0f;
tempMatrix.RotateLocal( m_axis, m_radians );
tempMatrix.PrintContents();
}
{
printf("Rotated local mat w=1\n");
Mth::Matrix tempMatrix2 = m_start;
m_axis[W] = 1.0f;
tempMatrix2.RotateLocal( m_axis, m_radians );
tempMatrix2.PrintContents();
}
printf( "Slerp axis=(%f %f %f %f) angle=%f\n", m_axis[X], m_axis[Y], m_axis[Z], m_axis[W], m_radians );
}
else
{
Dbg_Assert( 0 );
}
#endif
// If angle is too small, use lerp.
m_useLerp = m_radians < USE_LERP_INSTEAD_RADIANS;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void SlerpInterpolator::getMatrix( Matrix * result, float delta )
{
/* Cap and floor the delta */
/* If we are at one end the solution is easy */
if (delta <= 0.0f)
{
// delta = 0.0f;
*result = m_start;
return;
}
else if (delta >= 1.0f)
{
// delta = 1.0f;
*result = m_end;
return;
}
#if 0
// GJ: always lerp, used while slerp was being debugged
// m_useLerp = true;
#endif
/* Do the lerp if we are, else... */
if ( m_useLerp )
{
/* Get the lerp matrix */
Matrix lerp;
Vector lpos;
Vector spos;
Vector epos;
Vector rpos;
lerp.Ident();
spos = m_start[Mth::POS];
epos = m_end[Mth::POS];
lerp[Mth::RIGHT] = m_end[Mth::RIGHT] - m_start[Mth::RIGHT];
lerp[Mth::UP] = m_end[Mth::UP] - m_start[Mth::UP];
lerp[Mth::AT] = m_end[Mth::AT] - m_start[Mth::AT];
lpos = epos - spos;
/* Do lerp */
lerp[Mth::RIGHT].Scale( delta );
lerp[Mth::UP].Scale( delta );
lerp[Mth::AT].Scale( delta );
lpos.Scale( delta );
(*result)[Mth::RIGHT] = m_start[Mth::RIGHT] + lerp[Mth::RIGHT];
(*result)[Mth::UP] = m_start[Mth::UP] + lerp[Mth::UP];
(*result)[Mth::AT] = m_start[Mth::AT] + lerp[Mth::AT];
rpos = spos + lpos;
(*result)[Mth::RIGHT].Normalize();
(*result)[Mth::UP].Normalize();
(*result)[Mth::AT].Normalize();
(*result)[Mth::POS] = rpos;
}
else
{
Vector rpos;
Vector spos;
Vector epos;
Vector lpos;
spos = m_start[Mth::POS];
epos = m_end[Mth::POS];
/* Remove the translation for now */
*result = m_start;
(*result)[Mth::POS] = Mth::Vector( 0.0f, 0.0f, 0.0f );
/* Rotate the new matrix */
// m_axis[W] = 0.0f;
result->Rotate( m_axis, m_radians * delta );
/* Do linear interpolation on position */
lpos = epos - spos;
lpos.Scale( delta );
rpos = spos + lpos;
(*result)[Mth::POS] = rpos;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void SlerpInterpolator::invertDirection ( )
{
m_axis = -m_axis;
m_radians = (2.0f * Mth::PI) - m_radians;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Obj

102
Code/Core/Math/slerp.h Normal file
View File

@ -0,0 +1,102 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/slerp.h **
** **
** Created: 12/20/01 - gj **
** **
** Description: Slerp Interpolator Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_SLERP_H
#define __CORE_MATH_SLERP_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/math/vector.h>
#include <core/math/matrix.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/****************************************************************************
*
* Class: Slerp Interpolator
*
* Description: Slerp Interpolator math class
*
****************************************************************************/
class SlerpInterpolator
{
public:
SlerpInterpolator();
SlerpInterpolator( const Matrix* pStart, const Matrix* pEnd );
public:
void setMatrices( const Matrix* pStart, const Matrix* pEnd );
void getMatrix( Matrix* result, float delta );
void invertDirection ( );
float getRadians ( ) { return m_radians; }
const Mth::Vector& getAxis ( ) { return m_axis; }
protected:
Matrix m_start;
Matrix m_end;
Vector m_axis;
float m_radians;
bool m_useLerp; // do linear-interpolation, rather than slerping
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Mth
#endif // __CORE_MATH_SLERP_H

432
Code/Core/Math/vector.cpp Normal file
View File

@ -0,0 +1,432 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Vector (MTH) **
** **
** File name: vector.cpp **
** **
** Created by: 11/24/99 - Mick **
** **
** Description: Math Library code **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math.h>
#include <core/defines.h>
//#include <core/math.h>
#include <core/math/math.h>
#include <core/math/vector.h>
#include <core/math/matrix.h>
#include <core/macros.h>
#include <core/math/quat.h>
#include <core/math/vector.inl>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Mth
{
/*****************************************************************************
** DBG Information **
*****************************************************************************/
//
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
Vector& Vector::RotateY90( ERot90 angle )
{
float temp;
switch (angle)
{
case ROT_0:
break;
case ROT_90:
temp = col[X];
col[X] = col[Z];
col[Z] = -temp;
break;
case ROT_180:
col[X] = -col[X];
col[Z] = -col[Z];
break;
case ROT_270:
temp = col[X];
col[X] = -col[Z];
col[Z] = temp;
break;
default:
Dbg_MsgAssert(0, ("Vector::RotateY90() out of range: %d", angle));
break;
}
return *this;
}
/*****************************************************************************
// Project the vector onto the plane define by a normal
*****************************************************************************/
Vector& Vector::ProjectToPlane(const Vector& normal)
{
float perp_component = Mth::DotProduct(*this,normal);
*this -= normal * perp_component;
return *this;
}
Vector& Vector::RotateToPlane(const Vector& normal)
{
// get the length of the vector
float length = Length();
// Project the vector onto the plane
ProjectToPlane(normal);
// now we've projected it ontot he plane
// we need to handle the case where it dissapears into a point
// which would indicate that we were perpendicular to the plane
// so need to get an arbitary vector in the plane
float projected_length = Length();
if (projected_length == 0.0f) // is this a valid comparision?
{
// Rotate vector through -90 degrees about Y then +90 about X
col[X] = -normal[Z];
col[Y] = normal[X];
col[Z] = -normal[Y];
}
// get unit vector in this direction
Normalize();
// multiply by original speed to rotate velocity onto plane
*this *= length;
col[W] = 0.0f; // clean up W, otherwise multilications will accumelate over time...
return *this;
}
Vector& Vector::RotateToNormal(const Vector& normal)
{
*this = normal*Length();
return *this;
}
Vector& Vector::ProjectToNormal(const Vector& normal)
{
float dot = Mth::DotProduct(*this,normal);
*this = normal * dot;
return *this;
}
/* Finds the largest contributor to the length of the vector...
If you pass in whichAxis, it will fill it in with which axis
is the max...
*/
float Vector::GetMaxAxis( int *whichAxis )
{
int which_axis;
if ( !whichAxis )
{
whichAxis = &which_axis;
}
*whichAxis = X;
if ( Abs( this->col[ Y ] ) > Abs( this->col[ X ] ) )
{
if ( Abs( this->col[ Z ] ) > Abs( this->col[ Y ] ) )
*whichAxis = Z;
else
*whichAxis = Y;
}
else if ( Abs( this->col[ Z ] ) > Abs( this->col[ X ] ) )
{
*whichAxis = Z;
}
return ( this->col[ *whichAxis ] );
}
void Vector::DegreesToRadians( void )
{
this->col[ X ] = DEGREES_TO_RADIANS( this->col[ X ] );
this->col[ Y ] = DEGREES_TO_RADIANS( this->col[ Y ] );
this->col[ Z ] = DEGREES_TO_RADIANS( this->col[ Z ] );
}
void Vector::RadiansToDegrees( void )
{
this->col[ X ] = RADIANS_TO_DEGREES( this->col[ X ] );
this->col[ Y ] = RADIANS_TO_DEGREES( this->col[ Y ] );
this->col[ Z ] = RADIANS_TO_DEGREES( this->col[ Z ] );
}
void Vector::FeetToInches( void )
{
this->col[ X ] = FEET_TO_INCHES( this->col[ X ] );
this->col[ Y ] = FEET_TO_INCHES( this->col[ Y ] );
this->col[ Z ] = FEET_TO_INCHES( this->col[ Z ] );
}
// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )
void Vector::ConvertToMaxCoords( void )
{
this->col[ X ] = -this->col[ X ];
float temp = this->col[ Y ];
this->col[ Y ] = -this->col[ Z ];
this->col[ Z ] = temp;
}
// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )
void Vector::ConvertFromMaxCoords( void )
{
this->col[ X ] = -this->col[ X ];
float temp = this->col[ Y ];
this->col[ Y ] = this->col[ Z ];
this->col[ Z ] = -temp;
}
float GetAngle( const Matrix &currentOrientation, const Vector &desiredHeading, int headingAxis, int rotAxis )
{
Dbg_MsgAssert( headingAxis == X || headingAxis == Y || headingAxis == Z,( "Improper heading axis." ));
Dbg_MsgAssert( rotAxis == X || rotAxis == Y || rotAxis == Z,( "Improper rot axis." ));
Dbg_MsgAssert( rotAxis != headingAxis,( "Can't use heading axis as rot axis." ));
Mth::Vector tempHeading = desiredHeading;
tempHeading.ProjectToPlane( currentOrientation[ rotAxis ] );
if ( !tempHeading.Length( ) )
{
// If our rot axis is along Y, for example, the
// target heading is right above us... Can't pick
// a rotation!
return ( 0.0f );
}
tempHeading.Normalize( );
// while we have these two vectors, find the angle between them...
float angCos = DotProduct( currentOrientation[ headingAxis ], tempHeading );
// Mick: contrain Dot product to range -1.0f to +1.0f, since FP innacuracies might
// make it go outside this range
// (previously this was done only on NGC. Not sure why it has started failing now
// but it seems logical that it would fail occasionally, so this check is necessary)
float ang = angCos;
if ( ang > 1.0f ) ang = 1.0f;
if ( ang < -1.0f ) ang = -1.0f;
float retVal = -acosf( ang );
Mth::Vector temp = Mth::CrossProduct( currentOrientation[ headingAxis ], tempHeading );
// check to see if the cross product is in the same quatrant as our rot axis...
// if so, gots to rotate the other way and shit like that...
int whichAxis;
float tempMax = temp.GetMaxAxis( &whichAxis );
if ( ( tempMax > 0 ) == ( currentOrientation[ rotAxis ][ whichAxis ] > 0 ) )
{
return ( -retVal );
}
return ( retVal );
}
float GetAngle(Vector &v1, Vector &v2)
{
Vector a=v1;
Vector b=v2;
a.Normalize();
b.Normalize();
float dot = Mth::DotProduct(a,b);
if ( dot > 1.0f ) dot = 1.0f;
if ( dot < -1.0f ) dot = -1.0f;
return Mth::RadToDeg(acosf(dot));
}
// Returns true if the angle between a and b is greater than the passed Angle.
bool AngleBetweenGreaterThan(const Vector& a, const Vector& b, float Angle)
{
float dot=Mth::DotProduct(a,b);
float len=a.Length();
if (len<0.5f)
{
return false;
}
dot/=len;
len=b.Length();
if (len<0.5f)
{
return false;
}
dot/=len;
float TestAngleCosine=cosf(Mth::DegToRad(Angle));
if (dot>=0.0f)
{
return dot<TestAngleCosine;
}
else
{
if (TestAngleCosine>=0.0f)
{
return true;
}
else
{
return dot<TestAngleCosine;
}
}
}
// Mick:
// Given two vectors, v1 and v2 and an Axis vector
// return the amount that v1 would have to rotate about the Axis
// in order to be pointing in the same direction as v2
// when viewed along the Axis
//
// Typically, "Axis" will be the Y axis of the object (Like the skater)
// and v1 will be the Z direction
// which we want to rotate toward v2 (about Y)
//
// retunr value will be in the range -PI .. PI (-180 to 180 degrees)
float GetAngleAbout(Vector &v1, Vector &v2, Vector &Axis)
{
Axis.Normalize();
v1.ProjectToPlane(Axis);
v2.ProjectToPlane(Axis);
v1.Normalize();
v2.Normalize();
Vector v3 = Mth::CrossProduct(Axis,v1);
float v1_dot = Mth::DotProduct(v1,v2);
float v3_dot = Mth::DotProduct(v3,v2);
float angle = acosf(Mth::Clamp(v1_dot, -1.0f, 1.0f));
if (v3_dot < 0.0f)
{
angle = -angle;
}
return angle;
}
#ifdef DEBUG_OVERFLOW_VECTORS
const float& Vector::operator[] ( sint i ) const
{
// Dbg_MsgAssert (Abs(col[i]) < 1000000000.0f || col[i]==1.0e+30f,("vector component (%f) over a billion!!!",col[i]));
Dbg_MsgAssert (!isnanf(col[i]),("vector component [%d] (%f) not a number!!!!",i,col[i]));
// Dbg_MsgAssert (!isinff(col[i]),("vector component [%d] (%f) infinite!!!!",i,col[i]));
return col[i];
}
#endif
#ifdef DEBUG_UNINIT_VECTORS
const float& Vector::operator[] ( sint i ) const
{
// This assertion will catch any of the predefined NaN values that we initilize the vectors and matrix to
// when DEBUG_UNINIT_VECTORS is defined.
Dbg_MsgAssert ( (*(uint32*)(&col[i]) & 0xffffff00) != 0x7F800000,("uninitialized vector[%d] = 0x%x",i,(*(uint32*)(&col[i]))));
return col[i];
}
// for debugging purposes, this function is not inline when we want the
// uninitialized vector debugging
// as it makes it easier to track down wehre the problem is
Vector& Vector::operator= ( const Vector& v )
{
col[X] = v[X];
col[Y] = v[Y];
col[Z] = v[Z];
col[W] = v[W];
return *this;
}
#endif
/******************************************************************/
/* */
/* */
/******************************************************************/
void Vector::PrintContents() const
{
// printf( "-----------------\n" );
printf( "[%f %f %f %f]\n", col[X], col[Y], col[Z], col[W] );
// printf( "-----------------\n" );
}
}

242
Code/Core/Math/vector.h Normal file
View File

@ -0,0 +1,242 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math/Vector.h **
** **
** Created: 11/29/99 - mjb **
** **
** Description: Vector Math Class **
** **
*****************************************************************************/
#ifndef __CORE_MATH_VECTOR_H
#define __CORE_MATH_VECTOR_H
// (Mick) If this is defined, then vectors will be initialized to (0,0,0,1), and
// matrices to:
// (1,0,0,0)
// (0,1,0,0)
// (0,0,1,0)
// (0,0,0,1)
// This is sligtly differnet to before, where mats were intialized to all (0,0,0,1)
// since they were defined as an Array of vecotors
// This makes the code run about 3% slower (on PS2), which is why we don't use it
//#define __INITIALIZE_VECTORS__
// you can catch code that used to rely on this (and other bugs)
// by uncommenting the following line
// this will initilize the vectors to garbage values
// and check all accesses of vectors to see if these values
// have been left before using....
// (this requires a full recompile, and makes the code run really slow)
//#define DEBUG_UNINIT_VECTORS
// we also might want to catch situations where a component of a vector is very large
// which could indicate some potential overflow, especially if the W components is
// accumalating errors, getting unseemly large, then getting incorporated
// into an equation that involves X,Y,Z
// (see Quat::Rotate for an example)
//#define DEBUG_OVERFLOW_VECTORS
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/math/rot90.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
enum
{
X, Y, Z, W
};
namespace Mth
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class Quat; // forward refs
class Matrix;
/****************************************************************************
*
* Class: Vector
*
* Description: Vector math class
*
****************************************************************************/
class Vector
{
public:
// Made special enum so we can have a constructor that does not initialize
enum ENoInitType
{
NO_INIT
};
Vector ( );
Vector ( ENoInitType ); /// A constructor that doesn't init the members.
Vector ( float cx, float cy, float cz );
Vector ( float cx, float cy, float cz, float cw );
// Vector ( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f );
Vector ( const Vector& v );
Vector& operator= ( const Vector& v );
bool operator== ( const Vector& v ) const;
bool operator!= ( const Vector& v ) const;
Vector& operator+= ( const Vector& v );
Vector& operator-= ( const Vector& v );
Vector& operator*= ( const float s );
Vector& operator/= ( float s );
Vector& operator*= ( const Vector& v );
Vector& operator/= ( const Vector& v );
Vector& operator*= ( const Matrix& mat );
const float& operator[] ( sint i ) const;
float& operator[] ( sint i );
Vector& Set ( float cx = 0.0f, float cy = 0.0f, float cz = 0.0f, float cw = 1.0f );
float Length ( void ) const;
float LengthSqr ( void ) const;
Vector& Negate ( void ); // this = -this
Vector& Negate ( const Vector& src ); // this = -src
Vector& Normalize ( ); // faster version normlaizes to 1
Vector& Normalize ( float len);
Vector& ShearX ( float shy, float shz );
Vector& ShearY ( float shx, float shz );
Vector& ShearZ ( float shx, float shy );
Vector& RotateX ( float s, float c );
Vector& RotateY ( float s, float c );
Vector& RotateZ ( float s, float c );
Vector& RotateX ( float angle );
Vector& RotateY ( float angle );
Vector& RotateZ ( float angle );
Vector& Rotate ( const Quat& quat );
Vector& Rotate ( const Matrix& matrix );
Vector& Rotate ( const Vector& axis, const float angle );
// 90 degree increment Rotation (uses no multiplication)
Vector& RotateY90 ( ERot90 angle );
Vector& Scale ( float scale );
Vector& Scale ( const Vector& scale );
Vector& RotateToPlane(const Vector& normal);
Vector& RotateToNormal(const Vector& normal);
Vector& ProjectToPlane(const Vector& normal);
Vector& ProjectToNormal(const Vector& normal);
Vector& ZeroIfShorterThan ( float length );
Vector& ClampMin ( float min );
Vector& ClampMax ( float max );
Vector& Clamp ( float min = 0.0f, float max = 1.0f );
Vector& ClampMin ( Vector& min );
Vector& ClampMax ( Vector& max );
Vector& Clamp ( Vector& min, Vector& max );
float GetX ( void ) const;
float GetY ( void ) const;
float GetZ ( void ) const;
float GetW ( void ) const;
float GetMaxAxis ( int *whichAxis = NULL );
void DegreesToRadians( void );
void RadiansToDegrees( void );
void FeetToInches( void );
// convert to 3d studio max coords ( Z+ up, Y- forward, X to the right... )
void ConvertToMaxCoords( void );
void ConvertFromMaxCoords( void );
// debug info
void PrintContents() const;
private:
enum
{
NUM_ELEMENTS = 4
};
float col[NUM_ELEMENTS];
} nAlign(128);
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
Vector operator+ ( const Vector& v1, const Vector& v2 );
Vector operator- ( const Vector& v1, const Vector& v2 );
Vector operator* ( const Vector& v, const float s );
Vector operator* ( const float s, const Vector& v );
Vector operator* ( const Vector& v, const Matrix& m );
Vector operator/ ( const Vector& v, const float s );
Vector operator- ( const Vector& v );
float DotProduct ( const Vector& v1, const Vector& v2 );
Vector CrossProduct ( const Vector& v1, const Vector& v2 );
Vector Clamp ( const Vector& v, float min = 0.0f, float max = 1.0f );
Vector Clamp ( const Vector& v, Vector& min, Vector& max );
float Distance ( const Vector& v1, const Vector& v2 );
float DistanceSqr ( const Vector& v1, const Vector& v2 );
float GetAngle ( const Matrix &currentOrientation, const Vector &desiredHeading, int headingAxis = Z, int rotAxis = Y );
float GetAngle(Vector &v1, Vector &v2);
bool AngleBetweenGreaterThan(const Vector& a, const Vector& b, float Angle);
float GetAngleAbout(Vector &v1, Vector &v2, Vector &Axis);
bool Equal ( const Vector& v1, const Vector& v2, const float tol = 0.0001f );
Vector Lerp ( const Vector& v1, const Vector& v2, const float val );
Vector Min ( const Vector& v1, const Vector& v2 );
Vector Max ( const Vector& v1, const Vector& v2 );
Vector Min ( const Vector& v, float c );
Vector Max ( const Vector& v, float c );
void Swap ( Vector& a, Vector& b );
ostream& operator<< ( ostream& os, const Vector& v );
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Mth
#endif // __CORE_MATH_VECTOR_H

1205
Code/Core/Math/vector.inl Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,346 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: String **
** **
** File name: Core\String\CString.cpp **
** **
** Created by: 9/20/2000 - rjm **
** **
** Description: A handy, safe class to represent a string **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/string/cstring.h>
#include <sys/mem/memman.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Str
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
const int String::s_max_size = 256;
/*****************************************************************************
** Public Data **
*****************************************************************************/
int String::sDumbCount = 0;
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************************
*
* Function:
*
* Description: Default constructor
*
* Parameters:
*
*****************************************************************************/
String::String( void )
: mp_string( NULL )
{
//
m_dumbNum = sDumbCount;
sDumbCount++;
}
/******************************************************************************
*
* Description: First copy constructor
* (called by: String x = "blah";)
*
*****************************************************************************/
String::String( const char* string )
: mp_string ( NULL )
{
//
m_dumbNum = sDumbCount;
sDumbCount++;
// call operator= function
*this = string;
//Ryan("copy successful\n");
}
/******************************************************************************
*
* Description: Second copy constructor
*
*****************************************************************************/
String::String( const String& string )
: mp_string ( NULL )
{
//
// call operator= function
*this = string;
m_dumbNum = sDumbCount;
sDumbCount++;
}
/******************************************************************************
*
* Description: destructor
*
*****************************************************************************/
String::~String( void )
{
//
//Ryan("Am deleting string");
if (mp_string)
{
delete [] mp_string;
mp_string = NULL;
}
//Ryan("\n");
sDumbCount--;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
String & String::operator= (const char * string)
{
//
int last_char = 0;
if ( string )
{
last_char = strlen(string) - 1;
// Fix the case where "string" is the empty string
if( last_char < 0 )
{
last_char = 0;
}
}
copy(string, 0, last_char);
//Ryan("Copying %s to String\n", mp_string);
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
String & String::operator= (const String & string)
{
//
Dbg_MsgAssert(this != &string,( "can't assign a String to itself"));
// call other operator= function
*this = string.mp_string;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool String::operator== (const char * string)
{
//
//Ryan("comparing String to string: %s to %s\n", mp_string, string);
if (mp_string && string)
{
return (strcmp(mp_string, string) == 0);
}
return (!mp_string && !string);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool String::operator== (const String & string)
{
//
//Ryan("comparing String to String: %s to %s\n", mp_string, string.mp_string);
return (*this == string.mp_string);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool String::operator!()
{
return (mp_string == NULL);
}
/******************************************************************************
*
* Description: Returns pointer to internal char * array. Maybe should be const.
*
*****************************************************************************/
const char * String::getString() const
{
//
return mp_string;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void String::copy(const char *pChar, int first_char, int last_char)
{
if ( pChar && last_char >= first_char)
{
// GJ: The following handles 1-byte long strings incorrectly:
// if ( first_char == last_char )
if ( pChar[first_char] == 0 )
{
if (mp_string)
{
delete [] mp_string;
}
mp_string = new char[1];
mp_string[0] = 0;
m_length = 2; // MICK-GJ: Set length to 2, so it matches what we have below
}
else
{
int length = last_char - first_char + 2;
if (length < 4) length = 4;
Dbg_MsgAssert (length <= s_max_size,( "string too long for String object"));
// if current string exists and is smaller than new string, delete it
if ( mp_string && ( length > m_length ))
{
delete [] mp_string;
mp_string = NULL;
}
// if current string doesn't exist, or has been deleted, make a new one
if ( !mp_string )
{
m_length = length;
mp_string = new char[m_length];
}
// perform string copy
int i = 0;
int j;
for (j = first_char; j <= last_char; j++)
{
mp_string[i] = pChar[j];
i++;
}
mp_string[i] = '\0';
}
}
else
{
if ( mp_string )
{
delete [] mp_string;
mp_string = NULL;
}
}
//Ryan("copied string %s\n", pChar);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace String

113
Code/Core/String/CString.h Normal file
View File

@ -0,0 +1,113 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: String **
** **
** File name: Core\String\CString.h **
** **
** Created by: 9/20/2000 - rjm **
** **
** Description: A handy, safe class to represent a string **
** **
*****************************************************************************/
#ifndef __CORE_STRING_STRING_H
#define __CORE_STRING_STRING_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_SUPPORT_CLASS_H
#include <core/support/class.h>
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Str
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/****************************************************************************
*
* Class: String
*
* Description: A handy, safe class for representing a string.
*
* Usage: String x = "try our new diet of pinecones";
* String y = x;
* printf("%s\n", y.getString());
*
****************************************************************************/
class String : public Spt::Class // fix bug delete[] !!!
{
public:
String();
String(const char *string);
String(const String &string);
~String();
String& operator= (const char * string);
String& operator= (const String & string);
bool operator== (const char * string);
bool operator== (const String & string);
bool operator!();
const char* getString() const;
void copy(const char *pChar, int first_char, int last_char);
int m_dumbNum;
static int sDumbCount;
private:
char* mp_string;
int m_length;
static const int s_max_size;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace String
#endif // __CORE_STRING_STRING_H

View File

@ -0,0 +1,247 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: **
** **
** Module: String **
** **
** File name: stringutils.cpp **
** **
** Created by: 05/31/01 - Mick **
** **
** Description: useful string (char *) utilities **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <sys/config/config.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Str
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
#define Caseless(letter) (((letter)>='A' && (letter)<='Z')?((letter)+'a'-'A'):letter)
// Returns location of Needle in the Haystack
const char * StrStr (const char *pHay, const char *pNeedle)
{
register char First = *pNeedle++; // get first letter in needle
if (!First) return 0; // if end of needle, then return NULL
First = Caseless(First);
while (1)
{
while (1) // scan Haystack one letter at a time
{
char FirstHay = *pHay++; // get first letter of haystack
FirstHay = Caseless(FirstHay);
if (FirstHay == First) break; // first letter matches, so drop into other code
if (!FirstHay) return 0; // if end of haystack, then return NULL
}
const char *pH = pHay; // second letter of hay
const char *pN = pNeedle; // second letter of needle
while (1)
{
char n = *pN++; // get a needle letter
if (!n) return pHay-1; // end of needle, so return pointer to start of string in haystack
char h = *pH++; // get a hay letter
if (Caseless(n) != Caseless(h)) break; // difference, so stop looping (could be end of haystack, which is valid)
}
}
}
void LowerCase(char *p)
{
while (*p)
{
char letter = *p;
if (letter>='A' && letter<='Z')
letter+='a'-'A';
*p++ = letter;
}
}
void UpperCase(char *p)
{
while (*p)
{
char letter = *p;
if (letter>='a' && letter<='z')
letter-='a'-'A';
*p++ = letter;
}
}
int WhiteSpace(char *p)
{
if (*p == 0x20 || *p== 0x09)
return 1;
else
return 0;
}
char *PrintThousands(int n, char c)
{
static char buffer[32]; // enough for any int
char normal[32]; // printf in here without commas
char *p = buffer;
if (n<0)
{
*p++ = '-';
n = -n;
}
sprintf (normal, "%d", n);
int digits = strlen(normal);
char *p_digit = normal;
// Since other countries deliminate their successive kilos differently
switch (Config::GetLanguage())
{
case Config::LANGUAGE_FRENCH:
c=' ';
break;
case Config::LANGUAGE_SPANISH:
c='.';
break;
case Config::LANGUAGE_GERMAN:
c='.';
break;
case Config::LANGUAGE_ITALIAN:
c='.';
break;
default:
c=',';
break;
}
while (digits)
{
*p++ = *p_digit++;
digits--;
if ( digits && ( digits % 3) == 0)
{
*p++ = c;
}
}
*p++ = 0;
// printf ("%s\n",buffer);
return buffer;
}
// helper function for SText::Draw(), SFont::QueryString()
uint DehexifyDigit(const char *pLetter)
{
uint digit = 0;
if (*pLetter >= '0' && *pLetter <= '9')
digit = *pLetter - '0';
else if (*pLetter >= 'a' && *pLetter <= 'v')
digit = *pLetter - 'a' + 10;
else if (*pLetter >= 'A' && *pLetter <= 'V')
digit = *pLetter - 'A' + 10;
else
{
Dbg_MsgAssert(0, ("Non Hex digit"));
}
return digit;
}
// Returns
// -1 if a<b
// 0 -f a==b
// 1 if a>b
//
//
// if
int Compare(const char *p_a, const char *p_b)
{
for (;;)
{
char a = *p_a++;
char b = *p_b++;
a = Caseless(a);
b = Caseless(b);
if (a < b)
{
return -1;
}
if (a > b)
{
return 1;
}
if (!a && !b)
{
// strings are identical
return 0;
}
if (!a)
{
// a is shorter, so a < b
return -1;
}
if (!b)
{
// b is shorter, so b < a
return 1;
}
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Str

View File

@ -0,0 +1,80 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: **
** **
** Module: String **
** **
** File name: stringutils.h **
** **
** Created by: 05/31/01 - Mick **
** **
** Description: useful string (char *) utilities **
** **
*****************************************************************************/
#ifndef __CORE_STRING_STRINGUTILS_H
#define __CORE_STRING_STRINGUTILS_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Str
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
const char* StrStr(const char* pHay, const char* pNeedle);
void LowerCase(char* p);
void UpperCase(char* p);
int WhiteSpace(char* p);
char * PrintThousands(int n, char c = ',');
uint DehexifyDigit(const char *pLetter);
int Compare(const char *p_a, const char *p_b);
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Str
#endif // __DIR_SUBDIR_FILE_H

127
Code/Core/StringHashTable.h Normal file
View File

@ -0,0 +1,127 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core library **
** **
** Module: HashTable **
** **
** File name: Core\HashTable.h **
** **
** Created by: 9/22/2000 - rjm **
** **
** Description: A handy Hashtable class **
** **
*****************************************************************************/
#ifndef __CORE_LIST_STRINGHASHTABLE_H
#define __CORE_LIST_STRINGHASHTABLE_H
#ifndef __PLAT_WN32__
#include <sys/mem/PoolManager.h>
#endif
#include "HashTable.h"
namespace Crc
{
uint32 GenerateCRCFromString( const char *pName );
}
namespace Script
{
// So as not to require inclusion of checksum.h
#ifdef __NOPT_ASSERT__
const char *FindChecksumName(uint32 checksum);
#endif
}
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
template<class _V>
class StringHashTable : public HashTable<_V>
{
public:
StringHashTable(int numBits);
bool PutItem(const char *stringKey, _V *item);
_V * GetItem(const char *stringKey, bool assert_if_clash = true);
void FlushItem(const char *stringKey);
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template<class _V> //inline
StringHashTable<_V>::StringHashTable(int numBits) :
HashTable<_V>(numBits)
{
}
template<class _V> //inline
bool StringHashTable<_V>::PutItem(const char *stringKey, _V *item)
{
uint32 key = Crc::GenerateCRCFromString(stringKey);
return HashTable<_V>::PutItem(key, item);
}
template<class _V> //inline
_V *StringHashTable<_V>::GetItem(const char *stringKey, bool assert_if_clash)
{
uint32 key = Crc::GenerateCRCFromString(stringKey);
return HashTable<_V>::GetItem(key, assert_if_clash);
}
template<class _V> //inline
void StringHashTable<_V>::FlushItem(const char *stringKey)
{
uint32 key = Crc::GenerateCRCFromString(stringKey);
HashTable<_V>::FlushItem(key);
}
} // namespace Lst
#endif // __CORE_LIST_STRINGHASHTABLE_H

149
Code/Core/Support/Lock.h Normal file
View File

@ -0,0 +1,149 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** File name: core/support/lock.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_LOCK_H
#define __CORE_LOCK_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/support.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Spt
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class Access : public Spt::Class
{
public :
Access();
void Forbid( void );
void Permit( void );
void Enable( void );
bool HaveAccess( void );
private :
sint m_count;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline Access::Access()
: m_count( 0 )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Access::Forbid( void )
{
m_count++;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Access::Permit( void )
{
m_count--;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Access::Enable( void )
{
m_count = 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Access::HaveAccess ( void )
{
return( m_count == 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Spt
#endif // __CORE_LOCK_H

150
Code/Core/Support/Ref.h Normal file
View File

@ -0,0 +1,150 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** File name: core/support/lock.h **
** **
** Created: 03/16/00 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_REF_H
#define __CORE_REF_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/support.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Spt
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class Ref : public Spt::Class
{
public :
Ref();
Ref( const Ref& rhs );
void Acquire( void );
void Release( void );
bool InUse( void );
private :
sint m_count;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline Ref::Ref ()
: m_count( 0 )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Ref::Ref( const Ref& rhs )
: m_count( 0 )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Ref::Acquire ( void )
{
m_count++;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void Ref::Release ( void )
{
Dbg_MsgAssert(m_count>0,("Tried to call Release when m_count was already zero"));
m_count--;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool Ref::InUse ( void )
{
return ( m_count != 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Spt
#endif // __CORE_REF_H

272
Code/Core/Support/class.cpp Normal file
View File

@ -0,0 +1,272 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** File name: class.cpp **
** **
** Created by: 06/10/99 - mjb **
** **
** Description: Base class from which all other classes are derived. **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <core/defines.h>
#include <core/support.h>
#include <sys/mem/memman.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
#define NUM_ADDRESS 0 // Change this to 8 to have a handy list of addresses to check.
// If set to 0, no extra code/data will be generated.
// Remember to change to 8, compile, then get the addresses in question
// as the act of adding this code/data will change your addresses.
#if NUM_ADDRESS > 0
uint32 gAddress[NUM_ADDRESS] =
{
0x81701061,
0x81700ee1,
0x81700d61,
0x81700be1,
0x81700a61,
0x817008e1,
0x81700761,
0x817005e1
};
static void check_address( void * p, int size )
{
for ( int lp = 0; lp < 8; lp++ )
{
if ( gAddress[lp] == ((uint32)p) ) {
Dbg_Message( "We found the address we're looing for: 0x%08x (%d)\n", (uint32)p, size );
}
}
}
#else
#define check_address(a,b)
#endif
#ifdef __PLAT_NGC__
/******************************************************************/
/* */
/* */
/******************************************************************/
static inline void* operator new( size_t size )
{
// Dbg_SetPlacementNew( false );
void * rv = Mem::Manager::sHandle().New( size, true );
check_address( rv, size );
return rv;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
static inline void* operator new[] ( size_t size )
{
// Dbg_SetPlacementNew( false );
void * rv = Mem::Manager::sHandle().New( size, true );
check_address( rv, size );
return rv;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
static inline void operator delete( void* pAddr )
{
Mem::Manager::sHandle().Delete( pAddr );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
static inline void operator delete[]( void* pAddr )
{
Mem::Manager::sHandle().Delete( pAddr );
}
#endif // __PLAT_NGC__
namespace Spt
{
/******************************************************************/
/* new operators - same as global + zero-ed memory */
/* */
/******************************************************************/
#if (defined ( ZERO_CLASS_MEM ) && !defined ( __PLAT_WN32__ ))
void* Class::operator new( size_t size )
{
void* p_ret = Mem::Manager::sHandle().New( size );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new[] ( size_t size )
{
void* p_ret = Mem::Manager::sHandle().New( size );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new( size_t size, bool assert_on_fail )
{
void* p_ret = Mem::Manager::sHandle().New( size, assert_on_fail );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new[] ( size_t size, bool assert_on_fail )
{
void* p_ret = Mem::Manager::sHandle().New( size, assert_on_fail );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail )
{
void* p_ret = Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail )
{
void* p_ret = Mem::Manager::sHandle().New( size, assert_on_fail, pAlloc );
if ( p_ret )
{
memset ( p_ret, 0, size );
}
check_address( p_ret, size );
return p_ret;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new( size_t size, void* pLocation )
{
if ( pLocation )
{
memset ( pLocation, 0, size );
}
return pLocation;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* Class::operator new[]( size_t size, void* pLocation )
{
if ( pLocation )
{
memset ( pLocation, 0, size );
}
return pLocation;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif
} // namespace Spt

63
Code/Core/Support/class.h Normal file
View File

@ -0,0 +1,63 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** Created: 06/10/99 mjb **
** **
** File name: core/support/class.h **
** **
** Description: Base class from which classes are derived if they want **
** their memory zeroed when instantiated (via new) **
** **
*****************************************************************************/
#ifndef __CORE_SUPPORT_CLASS_H
#define __CORE_SUPPORT_CLASS_H
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
#define ZERO_CLASS_MEM TRUE
namespace Mem
{
class Allocator;
}
namespace Spt
{
class Class
{
public:
#if (defined ( ZERO_CLASS_MEM ) && !defined ( __PLAT_WN32__ ))
void* operator new( size_t size );
void* operator new[] ( size_t size );
void* operator new( size_t size, bool assert_on_fail );
void* operator new[] ( size_t size, bool assert_on_fail );
void* operator new( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true );
void* operator new[]( size_t size, Mem::Allocator* pAlloc, bool assert_on_fail = true );
void* operator new( size_t size, void* pLocation );
void* operator new[]( size_t size, void* pLocation );
#endif // ZERO_CLASS_MEM
};
} // namespace Spt
#endif // __CORE_SUPPORT_CLASS_H

View File

@ -0,0 +1,76 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** Created: 06/10/99 mjb **
** **
** File name: core/support/support.h **
** **
** Description: template class for tracking class hierarchy **
** **
*****************************************************************************/
#ifndef __CORE_SUPPORT_SUPPORT_H
#define __CORE_SUPPORT_SUPPORT_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifdef __PLAT_XBOX__
#include <typeinfo.h>
#else
#include <typeinfo>
#endif
#include <core/support/class.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
//#define class _c : public Spt::Class class _c : public Spt::Class
//#define class _c : public _b class _c : public _b
#define nTemplateBaseClass(_t,_c) \
template< class _t > \
class _c : public Spt::Class \
#define nTemplateBaseClass2(_t1,_t2,_c) \
template< class _t1, class _t2 > \
class _c : public Spt::Class \
#define nTemplateBaseClass3(_t1,_t2,_t3,_c) \
template< class _t1, class _t2, class _t3 > \
class _c : public Spt::Class \
#define nTemplateSubClass(_t,_c,_b) \
template< class _t > \
class _c : public _b \
#define nTemplateSubClass2(_t1,_t2,_c,_b) \
template< class _t1, class _t2 > \
class _c : public _b \
#define nTemplateSubClass3(_t1,_t2,_t3,_c,_b) \
template< class _t1, class _t2, class _t3 > \
class _c : public _b \
#define Dbg_TemplateBaseClass(_t1,_c)
#define Dbg_TemplateSubClass(_t1,_c,_b)
#define Dbg_TemplateBaseClass(_t1,_c)
#define Dbg_TemplateSubClass(_t1,_c,_b)
#define Dbg_TemplateBaseClass2(_t1,_t2,_c)
#define Dbg_TemplateSubClass2(_t1,_t2,_c,_b)
#endif // __CORE_SUPPORT_SUPPORT_H

67
Code/Core/Task.h Normal file
View File

@ -0,0 +1,67 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task (TSK) **
** **
** File name: core/task.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_TASK_H
#define __CORE_TASK_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/task/task.h>
#include <core/task/list.h>
#include <core/task/stack.h>
#include <core/task/hook.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
#endif // __CORE_TASK_H

158
Code/Core/Task/Hook.h Normal file
View File

@ -0,0 +1,158 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task (TSK_) **
** **
** File name: core/task/hook.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_TASK_HOOK_H
#define __CORE_TASK_HOOK_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/***********************************************************************
*
* Class: BaseHook
*
* Description: abstract base class for code hook
* defines minimal interface
*
***********************************************************************/
class BaseHook : public Spt::Class
{
public :
virtual void Call( void ) const = 0;
protected :
BaseHook( void ) {}
};
/***********************************************************************
*
* Class: Hook< _T >
*
* Description: derived template class for hook with typed data field
*
***********************************************************************/
nTemplateSubClass( _T, Hook, BaseHook )
{
public :
typedef void ( Code )( const Hook< _T >& );
Hook( Code* code, _T& data );
void Call( void ) const;
_T& GetData( void ) const;
private :
Code* const code;
_T& data;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template < class _T > inline
Hook< _T >::Hook( Code* _code, _T& _data )
: code( _code ), data( _data )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Hook< _T >::Call( void ) const
{
Dbg_AssertPtr( code );
code( *this );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_T& Hook< _T >::GetData( void ) const
{
Dbg_AssertType( &data, _T );
return data;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Tsk
#endif // __CORE_TASK_HOOK_H

108
Code/Core/Task/List.h Normal file
View File

@ -0,0 +1,108 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task (TSK_) **
** **
** File name: core/task/list.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_TASK_LIST_H
#define __CORE_TASK_LIST_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/list.h>
#include "core/support/lock.h"
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class BaseTask; // forward declaration
class List : public Spt::Access
{
public :
List ( void );
~List ( void );
void RemoveAllTasks ( void );
void Process ( bool time, uint mask );
void Dump ( void );
void AddTask ( BaseTask& task );
bool IsEmpty ( void );
void SignalListChange( void );
private :
Lst::Head<BaseTask> list;
uint stamp;
bool list_changed;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline bool List::IsEmpty ( void )
{
return list.IsEmpty();
}
} // namespace Tsk
#endif // __CORE_TASK_LIST_H

112
Code/Core/Task/Stack.h Normal file
View File

@ -0,0 +1,112 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task (TSK_) **
** **
** File name: core/task/stack.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_TASK_STACK_H
#define __CORE_TASK_STACK_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/task/task.h>
#include <core/task/list.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class Stack : public Spt::Access
{
public :
Stack ( void );
~Stack ( void );
void Push ( void );
void Pop ( void );
void Process ( bool time = false);
void Dump ( void );
void AddTask ( BaseTask& task );
void AddPushTask ( BaseTask& task );
void RemoveAllPushTasks ( void );
void RemoveAllTasks ( void );
void SetMask(uint mask);
private :
uint m_mask_off; // mask to supress execution of tasks
void remove_dead_entries( void );
class StackElement; // forward declaration
Lst::Head< StackElement > m_stack;
Lst::Head< StackElement > m_dead; // dead element list
StackElement* m_run; // current run task list
StackElement* m_add; // current add task list
// these get reset when Process() is called
bool m_pushedList;
bool m_poppedList;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
inline void Stack::SetMask(uint mask)
{
m_mask_off = mask;
}
} // namespace Tsk
#endif // __CORE_TASK_STACK_H

162
Code/Core/Task/Task.cpp Normal file
View File

@ -0,0 +1,162 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task Manager (TSK) **
** **
** File name: task.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Task Support **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/task.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
BaseTask::BaseTask( Node::Priority priority )
: tlist(NULL), stamp(0)
{
m_mask = 0; // default to "No type of thing", so it will always run
node = new Node( this, priority );
Dbg_AssertType( node, Node );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
BaseTask::~BaseTask ()
{
if ( tlist )
{
Remove();
}
Dbg_AssertType( node, Node );
delete node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void BaseTask::Remove( void )
{
if ( tlist )
{
tlist->Forbid();
tlist->SignalListChange();
node->Remove();
tlist->Permit();
tlist = NULL;
}
else
{
Dbg_Warning( "Task is not in a List" );
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool BaseTask::InList( void ) const
{
return node->InList();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void BaseTask::SetPriority( Node::Priority pri ) const
{
node->SetPri( pri );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Tsk

206
Code/Core/Task/Task.h Normal file
View File

@ -0,0 +1,206 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task (TSK_) **
** **
** File name: core/task/task.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_TASK_TASK_H
#define __CORE_TASK_TASK_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/list.h>
#include <core/task/list.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class BaseTask : public Spt::Access
{
friend class List;
public:
typedef Lst::Node< BaseTask > Node;
bool InList( void ) const;
void Remove( void );
virtual void vCall( void ) const = 0;
virtual void * GetCode(void) const = 0;
void SetPriority( Node::Priority pri ) const;
virtual ~BaseTask( void );
void SetMask(uint mask);
uint GetMask();
protected:
BaseTask( Node::Priority pri );
Node* node; // link node
private:
List* tlist; // task list to which we belong
uint stamp; // process stamp
uint m_mask; // mask indicating what types of thing this is
};
/******************************************************************/
/* */
/* */
/******************************************************************/
nTemplateSubClass( _T, Task, BaseTask )
{
public:
typedef void (Code)( const Task< _T >& );
Task( Code* const code, _T& data, Node::Priority pri = Lst::Node< BaseTask >::vNORMAL_PRIORITY );
virtual void vCall( void ) const;
_T& GetData( void ) const;
virtual void * GetCode(void) const;
private :
Code* const code; // tasks entry point
_T& data; // task defined data
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template < class _T > inline
Task< _T >::Task ( Code* const _code, _T& _data, Node::Priority pri )
: BaseTask( pri ), code( _code ), data( _data )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Task< _T >::vCall( void ) const
{
Dbg_AssertPtr( code );
code( *this );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_T& Task< _T >::GetData( void ) const
{
Dbg_AssertType( &data, _T );
return data;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void * Task< _T >::GetCode( void ) const
{
return (void*)code;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void BaseTask::SetMask( uint mask )
{
m_mask = mask;
}
inline uint BaseTask::GetMask( void )
{
return m_mask;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Tsk
#endif // __CORE_TASK_TASK_H

291
Code/Core/Task/Tlist.cpp Normal file
View File

@ -0,0 +1,291 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task Manager (TSK) **
** **
** File name: tlist.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Task List Support **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/task.h>
#include <sys/profiler.h> // Including for debugging
#include <sys/timer.h> // Including for debugging
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
List* TSK_BkGndTasks = NULL;
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
List::List( void )
: stamp( 0 ), list_changed( false )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
List::~List ( void )
{
Dbg_MsgAssert( list.IsEmpty(),( "Task List Not Empty" ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void List::Process( bool time, uint mask )
{
if ( !HaveAccess ())
{
return;
}
stamp++;
do
{
Lst::Search<BaseTask> iterator;
BaseTask* next = iterator.FirstItem( list );
list_changed = false;
while ( next )
{
BaseTask* task = next;
Dbg_AssertType( task, BaseTask );
Dbg_AssertPtr( task );
Dbg_AssertPtr( task->node );
Dbg_MsgAssert( task->node->InList(),( "Task was removed from list by previous task" ));
next = iterator.NextItem(); // get next task before we execute the current
// one as the task might remove itself
Dbg_MsgAssert(!list_changed,( "list changed, you fucker"));
if ( task->HaveAccess() )
{
if ( task->stamp != stamp )
{
task->stamp = stamp;
#ifdef __USE_PROFILER__
Tmr::MicroSeconds start_time=0;
#ifdef __PLAT_NGPS__
Tmr::MicroSeconds end_time=0;
#endif
if (time)
{
start_time = Tmr::GetTimeInUSeconds();
}
#endif
// only call the task if it is not masked off
if (! (task->GetMask() & mask))
{
task->vCall();
}
#ifdef __USE_PROFILER__
#ifdef __PLAT_NGPS__
if (time)
{
end_time = Tmr::GetTimeInUSeconds();
int length = (int)(end_time - start_time);
int size;
printf ("%6d %s\n",length,MemView_GetFunctionName((int)task->GetCode(), &size));
}
#endif
#endif
}
}
if ( list_changed )
{
break;
}
}
} while ( list_changed );
}
/******************************************************************/
// Mick Debugging: Dump out the contents of the task list
//
/******************************************************************/
void List::Dump( void )
{
Lst::Search<BaseTask> iterator;
BaseTask* next = iterator.FirstItem( list );
list_changed = false;
while ( next )
{
BaseTask* task = next;
Dbg_AssertType( task, BaseTask );
Dbg_AssertPtr( task );
Dbg_AssertPtr( task->node );
next = iterator.NextItem(); // get next task before we execute the current
// one as the task might remove itself
#ifdef __PLAT_NGPS__
if ( task->HaveAccess() )
{
// char *MemView_GetFunctionName(int pc, int *p_size);
// task->vCall();
int size;
printf ("Task %p %s\n",task->GetCode(),
MemView_GetFunctionName((int)task->GetCode(), &size));
}
#elif defined( __PLAT_NGC__ )
if ( task->HaveAccess() )
{
// char *MemView_GetFunctionName(int pc, int *p_size);
// task->vCall();
Dbg_Printf ("Task %p\n",task->GetCode() );
// MemView_GetFunctionName((int)task->GetCode(), &size));
}
#endif
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void List::AddTask( BaseTask& task )
{
Dbg_AssertType( &task, BaseTask );
Dbg_MsgAssert( !task.node->InList(),( "Task is already in a list" ));
Forbid (); // stop any processing while list is modified
list.AddNode( task.node );
task.tlist = this;
task.stamp = stamp - 1;
list_changed = true;
Permit();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void List::RemoveAllTasks( void )
{
Lst::Search<BaseTask> iterator;
BaseTask* next;
Forbid();
while (( next = iterator.FirstItem( list ) ))
{
next->Remove();
list_changed = true;
}
Permit();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void List::SignalListChange( void )
{
list_changed = true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Tsk

377
Code/Core/Task/Tstack.cpp Normal file
View File

@ -0,0 +1,377 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Task Manager (TSK) **
** **
** File name: tstack.cpp **
** **
** Created by: 05/27/99 - mjb **
** **
** Description: Task Stack Support **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/task.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Tsk
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
class Stack::StackElement : public List
{
friend class Stack;
public :
StackElement( void );
~StackElement( void );
private:
Lst::Node< StackElement >* m_node;
};
/*****************************************************************************
** Private Data **
*****************************************************************************/
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
void Stack::remove_dead_entries( void )
{
Lst::Search< StackElement > iterator;
StackElement* dead_entry;
Dbg_MsgAssert( HaveAccess(),( "List currently being processed" ));
while (( dead_entry = iterator.FirstItem( m_dead )))
{
delete dead_entry;
}
}
/*****************************************************************************
** Public Functions **
*****************************************************************************/
Stack::StackElement::StackElement( void )
{
m_node = new Lst::Node< StackElement >( this );
Dbg_AssertType( m_node, Lst::Node< StackElement > );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Stack::StackElement::~StackElement ( void )
{
Dbg_AssertType( m_node, Lst::Node< StackElement > );
delete m_node;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Stack::Stack ( void )
{
m_pushedList = false;
m_poppedList = false;
Push(); // create initial list
m_add = m_run;
m_pushedList = false;
m_poppedList = false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
Stack::~Stack ( void )
{
Dbg_MsgAssert( HaveAccess(),( "List currently being processed" ));
Dbg_Code
(
if ( m_stack.CountItems() != 1 )
{
Dbg_Warning( "Task Stack contains %d Task Lists", m_stack.CountItems());
}
)
while ( m_stack.CountItems() )
{
Pop ();
}
remove_dead_entries();
Dbg_MsgAssert (( m_run == NULL ),( "Task Stack not empty" ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::Push( void )
{
/*
On entry:
m_add -> top list on stack (the one being processed)
m_run -> probably the same
On exit:
m_run -> new top list
m_add -> old top list (the one being processed)
*/
Dbg_MsgAssert(!m_pushedList,( "push already called this frame"));
m_run = new StackElement;
Dbg_AssertType( m_run, StackElement );
m_stack.AddToHead( m_run->m_node ); // deferred push
m_pushedList = true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::Pop( void )
{
/*
On entry:
m_add -> top list on stack (the one being processed)
m_run -> top list on stack
On exit:
m_run and m_add -> the new top list (originally second to top)
m_dead -> list to be destroyed (still being processed)
*/
Dbg_AssertType( m_run, StackElement );
// this assert is problematic because the task system does not call Process() on the input
// task list stacks for inactive devices, though Push() and Pop() are called
//Dbg_MsgAssert(!m_poppedList,( "pop already called this frame"));
// remove item
Lst::Search< StackElement > iterator;
iterator.FirstItem( m_stack );
// must use this test, m_pushedList is not reliable
if (m_add == m_run)
m_add = iterator.NextItem();
else
{
// otherwise, current list is retained, m_add stays the same
m_pushedList = false;
}
// m_run may have been just added this frame, but that shouldn't matter
Dbg_MsgAssert( m_run->IsEmpty(),( "Tasks List not Empty" ));
if( HaveAccess() )
{
delete m_run;
}
else
{
m_run->m_node->Remove();
m_dead.AddToHead( m_run->m_node ); // deferred kill
}
m_run = m_add;
m_poppedList = true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::Process( bool time )
{
Forbid();
Dbg_AssertType( m_run, StackElement );
m_add = m_run; // push now in effect
m_run->Process( time, m_mask_off );
Permit();
remove_dead_entries();
m_pushedList = false;
m_poppedList = false;
}
void Stack::Dump( void )
{
Forbid();
Dbg_AssertType( m_run, StackElement );
m_add = m_run; // push now in effect
m_run->Dump();
Permit();
remove_dead_entries();
m_pushedList = false;
m_poppedList = false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::AddTask( BaseTask& task )
{
Dbg_AssertType( &task, BaseTask );
Dbg_AssertType( m_add, StackElement );
m_add->AddTask( task );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::AddPushTask( BaseTask& task )
{
Dbg_AssertType( &task, BaseTask );
Dbg_AssertType( m_run, StackElement );
m_run->AddTask( task );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::RemoveAllTasks( void )
{
// we may really be removing all tasks in list about to be pushed
if (m_pushedList)
{
RemoveAllPushTasks();
Dbg_MsgAssert( m_run->IsEmpty(),( "should now be empty" ));
return;
}
Dbg_AssertType( m_add, StackElement );
m_add->RemoveAllTasks();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void Stack::RemoveAllPushTasks( void )
{
Dbg_AssertType( m_run, StackElement );
m_run->RemoveAllTasks();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Tsk

View File

@ -0,0 +1,70 @@
///******************************************************************
//*
//* DESCRIPTION: thread/ngps/t_thread.cpp
//*
//* AUTHOR: JAB
//*
//* HISTORY:
//*
//* DATE:9/1/2000
//*
//*******************************************************************/
//
///** include files **/
//
//#include <core/defines.h>
//#include <core/target.h>
//#include <core/task.h>
////#include <eekernel.h>
//
//#include "t_thread.h"
//
////#ifdef __NOPT_STD_MEM__
//extern "C" int _std_stack[1];
//static int* _stack = _std_stack;
////#else
////extern "C" int _dbg_stack[1];
////static int* _stack = _dbg_stack;
////#endif
//
//extern "C" int _stack_size[1];
//extern "C" int _start(void);
//
//Thread::PerThreadStruct _rootThreadStruct =
//{
// "ROOT",
// 0,
// 0,
// _start, // m_pEntry
// _stack, // m_pStackBase
// (int)_stack_size, // m_iStackSize
// 0,
// 0
//};
//
//int Thread::dummy = -1;
//
//
//namespace Thread
//{
// Dbg_Module
//
//// PJR - Commented out.
//// HTHREAD CreateThread( PerThreadStruct* pPTS )
//// {
//// ThreadParam sParam;
//// sParam.entry = pPTS->m_pEntry;
//// sParam.stack = pPTS->m_pStackBase;
//// sParam.stackSize = pPTS->m_iStackSize;
//// //ps2memset( pPTS->m_pStackBase, 0xca, pPTS->m_iStackSize);
//// sParam.initPriority = pPTS->m_iInitialPriority;
//// sParam.gpReg = pPTS;
////#ifdef __THREAD_DEBUGGING_PRINTS__
//// Dbg_Message( "T::CrThread: %s, entry 0x%x, stack 0x%x, size 0x%x\n",pPTS->m_cID, (unsigned int) pPTS->m_pEntry, (unsigned int) pPTS->m_pStackBase, (unsigned int) pPTS->m_iStackSize );
////#endif
//// pPTS->m_osId = ::CreateThread( &sParam );
//// return (HTHREAD) pPTS;
//// }
//}

View File

@ -0,0 +1,70 @@
/*******************************************************************
*
* DESCRIPTION: thread/ngc/t_thread.h
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/1/2000
*
*******************************************************************/
/** include files **/
#ifndef __CORE_THREAD_NGC_T_THREAD_H__
#define __CORE_THREAD_NGC_T_THREAD_H__
#include <core/support.h>
//#include <eekernel.h>
namespace Thread {
typedef int THREADID; // Id for use and assigned by application
typedef int OSTHREADID; // Id assigned by the OS.
typedef unsigned int HTHREAD; // A value that is easy to determine from the OS
class PerThreadStruct {
public:
char m_cID[16]; // a text name so its easy to
THREADID m_utid; // an id that the use can assign
OSTHREADID m_osId; // an id that the OS assigns
void* m_pEntry;
void* m_pStackBase;
int m_iStackSize;
int m_iInitialPriority;
void* m_pRpcData; // ptr to rpc specific data.
};
// PJR - Not sure...
// register PerThreadStruct* g_pCurrThread asm ("gp"); // Gotta fucking love that, eh?
// inline THREADID GetCurrentThreadId() { return (g_pCurrThread) ? g_pCurrThread->m_utid : 0; }
// inline HTHREAD GetCurrentHandle() { return (HTHREAD) g_pCurrThread; } // This is fastest, so use it if you want to get data fast;
//inline void StartThread( HTHREAD hthr, void* arg = NULL ) { ::StartThread( ((PerThreadStruct*)hthr)->m_osId, arg ); }
// So you must set up the stack, and the perthreadstruct.
HTHREAD CreateThread( PerThreadStruct* pPTS );
/*
Commentary on data for submodules (eg m_pRpcData):
Yes there are less data dependent ways of doing this. For example,
by having an array of pointers and the subsystem requests an index
that it can use. But the extra work (small tho it is) seems a bit
pointless when the penalty for hardcoding it is having to recompile
lots of things if it changes. Not a big deal.
*/
extern int dummy;
};
struct PTS{
char m_cID[16]; // a text name so its easy to
Thread::THREADID m_utid; // an id that the use can assign
Thread::OSTHREADID m_osId; // an id that the OS assigns
void* m_pEntry;
void* m_pStackBase;
int m_iStackSize;
int m_iInitialPriority;
void* m_pRpcData; // ptr to rpc specific data.
};
extern "C" Thread::PerThreadStruct _rootThreadStruct;
#endif // __CORE_THREAD_NGC_T_THREAD_H__

View File

@ -0,0 +1,71 @@
/*******************************************************************
*
* DESCRIPTION: thread/ngps/t_thread.cpp
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/1/2000
*
*******************************************************************/
/** include files **/
#include <core/defines.h>
#include <core/task.h>
#include <eekernel.h>
#include "t_thread.h"
extern "C" int _std_stack[8];
static int* _stack = _std_stack;
extern "C" int _stack_size[8];
extern "C" int _start(void);
Thread::PerThreadStruct _rootThreadStruct =
{
"ROOT",
0,
0,
_start, // m_pEntry
_stack, // m_pStackBase
(int)_stack_size, // m_iStackSize
0,
0
};
int Thread::dummy = -1;
typedef void (*VOID_CB)(void*); // pointer to function that takes a void pointer
namespace Thread
{
HTHREAD CreateThread( PerThreadStruct* pPTS )
{
ThreadParam sParam;
/*sParam.entry = pPTS->m_pEntry;*/
sParam.entry = (VOID_CB) (pPTS->m_pEntry);
sParam.stack = pPTS->m_pStackBase;
sParam.stackSize = pPTS->m_iStackSize;
//ps2memset( pPTS->m_pStackBase, 0xca, pPTS->m_iStackSize);
sParam.initPriority = pPTS->m_iInitialPriority;
sParam.gpReg = &_gp;
#ifdef __THREAD_DEBUGGING_PRINTS__
Dbg_Message( "T::CrThread: %s, entry 0x%x, stack 0x%x, size 0x%x\n",pPTS->m_cID, (unsigned int) pPTS->m_pEntry, (unsigned int) pPTS->m_pStackBase, (unsigned int) pPTS->m_iStackSize );
#endif
pPTS->m_osId = ::CreateThread( &sParam );
return (HTHREAD) pPTS;
}
}

View File

@ -0,0 +1,67 @@
/*******************************************************************
*
* DESCRIPTION: thread/ngps/t_thread.h
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/1/2000
*
*******************************************************************/
/** include files **/
#ifndef __CORE_THREAD_NGPS_T_THREAD_H__
#define __CORE_THREAD_NGPS_T_THREAD_H__
#include <core/support.h>
#include <eekernel.h>
namespace Thread {
typedef int THREADID; // Id for use and assigned by application
typedef int OSTHREADID; // Id assigned by the OS.
typedef unsigned int HTHREAD; // A value that is easy to determine from the OS
class PerThreadStruct {
public:
char m_cID[16]; // a text name so its easy to
THREADID m_utid; // an id that the use can assign
OSTHREADID m_osId; // an id that the OS assigns
void* m_pEntry;
void* m_pStackBase;
int m_iStackSize;
int m_iInitialPriority;
void* m_pRpcData; // ptr to rpc specific data.
};
//inline void StartThread( HTHREAD hthr, void* arg = NULL ) { ::StartThread( ((PerThreadStruct*)hthr)->m_osId, arg ); }
// So you must set up the stack, and the perthreadstruct.
HTHREAD CreateThread( PerThreadStruct* pPTS );
/*
Commentary on data for submodules (eg m_pRpcData):
Yes there are less data dependent ways of doing this. For example,
by having an array of pointers and the subsystem requests an index
that it can use. But the extra work (small tho it is) seems a bit
pointless when the penalty for hardcoding it is having to recompile
lots of things if it changes. Not a big deal.
*/
extern int dummy;
};
struct PTS{
char m_cID[16]; // a text name so its easy to
Thread::THREADID m_utid; // an id that the use can assign
Thread::OSTHREADID m_osId; // an id that the OS assigns
void* m_pEntry;
void* m_pStackBase;
int m_iStackSize;
int m_iInitialPriority;
void* m_pRpcData; // ptr to rpc specific data.
};
extern "C" Thread::PerThreadStruct _rootThreadStruct;
#endif // __CORE_THREAD_NGPS_T_THREAD_H__

View File

@ -0,0 +1,36 @@
/*******************************************************************
*
* DESCRIPTION: t_target.h
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/5/2000
*
This is a dummy file, because its in the NGPS version
it has to be here too.
*******************************************************************/
/** include files **/
/** local definitions **/
/* default settings */
/** external functions **/
/** external data **/
/** internal functions **/
/** public data **/
/** private data **/
/** public functions **/
/** private functions **/

View File

@ -0,0 +1,36 @@
/*******************************************************************
*
* DESCRIPTION: t_target.h
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/5/2000
*
This is a dummy file, because its in the NGPS version
it has to be here too.
*******************************************************************/
/** include files **/
/** local definitions **/
/* default settings */
/** external functions **/
/** external data **/
/** internal functions **/
/** public data **/
/** private data **/
/** public functions **/
/** private functions **/

173
Code/Core/TimestampedFlag.h Normal file
View File

@ -0,0 +1,173 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Standard Header **
** **
** File name: core/TimestampedFlag.h **
** **
** Created: 3/3/3 - Dan **
** **
*****************************************************************************/
#ifndef __CORE_TIMESTAMPEDFLAG_H
#define __CORE_TIMESTAMPEDFLAG_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <sys/timer.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/************************************************************************
* *
* Class: TimestampedFlag *
* *
* Description: Flag which remembers the time of its last *
* modification *
* Extracted from skater.h *
* *
* *
***********************************************************************/
class CTimestampedFlag : public Spt::Class
{
public:
void Set ( bool state );
void SetTrue ( );
void SetFalse ( );
void Toggle ( );
bool Get ( );
Tmr::Time GetTime ( );
Tmr::Time GetElapsedTime ( );
operator bool ( ) { return Get(); }
private:
bool m_state; // flag state
Tmr::Time m_time; // time of last state change
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CTimestampedFlag::Set ( bool state )
{
if (m_state == state)
{
return;
}
m_state = state;
m_time = Tmr::GetTime();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CTimestampedFlag::SetTrue ( )
{
Set(true);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CTimestampedFlag::SetFalse ( )
{
Set(false);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CTimestampedFlag::Toggle ( )
{
Set(!m_state);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline bool CTimestampedFlag::Get ( )
{
return m_state;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Tmr::Time CTimestampedFlag::GetTime ( )
{
return m_time;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline Tmr::Time CTimestampedFlag::GetElapsedTime ( )
{
return Tmr::GetTime() - GetTime();
}
#endif // __CORE_TIMESTAMPEDFLAG_H

392
Code/Core/compress.cpp Normal file
View File

@ -0,0 +1,392 @@
#include <core/compress.h>
#define N 4096 /* size of ring buffer */
#define F 18 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length
if match_length is greater than this */
#define NIL N /* index for root of binary search trees */
unsigned long int
textsize = 0, /* text size counter */
codesize = 0, /* code size counter */
printcount = 0; /* counter for reporting progress every 1K bytes */
//unsigned char text_buf[N + F - 1]; //ring buffer of size N, with extra F-1 bytes to facilitate string comparison
int match_position, match_length; // of longest match. These are set by the InsertNode() procedure.
//int lson[N + 1], rson[N + 257], dad[N + 1]; // left & right children & parents -- These constitute binary search trees.
unsigned char *text_buf;
int *lson;
int *rson;
int *dad;
#define readc() *pIn++
#define writec(x) *pOut++ = x
void InitTree(void) /* initialize trees */
{
int i;
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());
text_buf = new unsigned char[N + F - 1];
lson = new int[N+1];
rson = new int[N+257];
dad = new int[N+1];
Mem::Manager::sHandle().PopContext(); //Mem::Manager::sHandle().TopDownHeap());
/* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
left children of node i. These nodes need not be initialized.
Also, dad[i] is the parent of node i. These are initialized to
NIL (= N), which stands for 'not used.'
For i = 0 to 255, rson[N + i + 1] is the root of the tree
for strings that begin with character i. These are initialized
to NIL. Note there are 256 trees. */
for ( i = N + 1; i <= N + 256; i++ ) rson[i] = NIL;
for ( i = 0; i < N; i++ ) dad[i] = NIL;
}
void DeInitTree(void) /* free up the memory */
{
delete [] text_buf;
delete [] lson;
delete [] rson;
delete [] dad;
}
void InsertNode(int r)
/* Inserts string of length F, text_buf[r..r+F-1], into one of the
trees (text_buf[r]'th tree) and returns the longest-match position
and length via the global variables match_position and match_length.
If match_length = F, then removes the old node in favor of the new
one, because the old one will be deleted sooner.
Note r plays double role, as tree node and position in buffer. */
{
int i, p, cmp;
unsigned char *key;
cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
rson[r] = lson[r] = NIL; match_length = 0;
for ( ; ; )
{
if ( cmp >= 0 )
{
if ( rson[p] != NIL )
{
p = rson[p];
}
else
{
rson[p] = r; dad[r] = p; return;
}
}
else
{
if ( lson[p] != NIL )
{
p = lson[p];
}
else
{
lson[p] = r; dad[r] = p; return;
}
}
for ( i = 1; i < F; i++ )
{
if ( (cmp = key[i] - text_buf[p + i]) != 0 ) break;
}
if ( i > match_length )
{
match_position = p;
if ( (match_length = i) >= F )
{
break;
}
}
}
dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
dad[lson[p]] = r; dad[rson[p]] = r;
if ( rson[dad[p]] == p )
{
rson[dad[p]] = r;
}
else
{
lson[dad[p]] = r;
}
dad[p] = NIL; /* remove p */
}
void DeleteNode(int p) /* deletes node p from tree */
{
int q;
if ( dad[p] == NIL ) return; /* not in tree */
if ( rson[p] == NIL ) q = lson[p];
else if ( lson[p] == NIL ) q = rson[p];
else
{
q = lson[p];
if ( rson[q] != NIL )
{
do
{
q = rson[q];
} while ( rson[q] != NIL );
rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
lson[q] = lson[p]; dad[lson[p]] = q;
}
rson[q] = rson[p]; dad[rson[p]] = q;
}
dad[q] = dad[p];
if ( rson[dad[p]] == p ) rson[dad[p]] = q;
else lson[dad[p]] = q;
dad[p] = NIL;
}
int Encode(char *pIn, char *pOut, int bytes_to_read, bool print_progress)
{
int i, c, len, r, s, last_match_length, code_buf_ptr;
unsigned char code_buf[17], mask;
textsize = 0; /* text size counter */
codesize = 0; /* code size counter */
printcount = 0; /* counter for reporting progress every 1K bytes */
InitTree(); /* initialize trees */
code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
code_buf[0] works as eight flags, "1" representing that the unit
is an unencoded letter (1 byte), "0" a position-and-length pair
(2 bytes). Thus, eight units require at most 16 bytes of code. */
code_buf_ptr = mask = 1;
s = 0; r = N - F;
for ( i = s; i < r; i++ ) text_buf[i] = ' '; /* Clear the buffer with
any character that will appear often. */
for ( len = 0; len < F && bytes_to_read; len++ )
{
c = readc();
bytes_to_read--;
text_buf[r + len] = c; /* Read F bytes into the last F bytes of
the buffer */
}
if ( (textsize = len) == 0 )
{
DeInitTree();
return 0; /* text of size zero */
}
for ( i = 1; i <= F; i++ ) InsertNode(r - i); /* Insert the F strings,
each of which begins with one or more 'space' characters. Note
the order in which these strings are inserted. This way,
degenerate trees will be less likely to occur. */
InsertNode(r); /* Finally, insert the whole string just read. The
global variables match_length and match_position are set. */
do
{
if ( match_length > len ) match_length = len; /* match_length
may be spuriously long near the end of text. */
if ( match_length <= THRESHOLD )
{
match_length = 1; /* Not long enough match. Send one byte. */
code_buf[0] |= mask; /* 'send one byte' flag */
code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */
}
else
{
code_buf[code_buf_ptr++] = (unsigned char) match_position;
code_buf[code_buf_ptr++] = (unsigned char)
(((match_position >> 4) & 0xf0)
| (match_length - (THRESHOLD + 1))); /* Send position and
length pair. Note match_length > THRESHOLD. */
}
if ( (mask <<= 1) == 0 )
{ /* Shift mask left one bit. */
for ( i = 0; i < code_buf_ptr; i++ ) /* Send at most 8 units of */
writec(code_buf[i]); /* code together */
codesize += code_buf_ptr;
code_buf[0] = 0; code_buf_ptr = mask = 1;
}
last_match_length = match_length;
for ( i = 0; i < last_match_length &&
bytes_to_read; i++ )
{
c = readc();
bytes_to_read--;
DeleteNode(s); /* Delete old strings and */
text_buf[s] = c; /* read new bytes */
if ( s < F - 1 ) text_buf[s + N] = c; /* If the position is
near the end of buffer, extend the buffer to make
string comparison easier. */
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
/* Since this is a ring buffer, increment the position
modulo N. */
InsertNode(r); /* Register the string in text_buf[r..r+F-1] */
}
if ( (textsize += i) > printcount )
{
// printf("%12ld\r", textsize); printcount += 1024;
/* Reports progress each time the textsize exceeds
multiples of 1024. */
}
while ( i++ < last_match_length )
{ /* After the end of text, */
DeleteNode(s); /* no need to read, but */
s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
if ( --len ) InsertNode(r); /* buffer may not be empty. */
}
} while ( len > 0 ); /* until length of string to be processed is zero */
if ( code_buf_ptr > 1 )
{ /* Send remaining code. */
for ( i = 0; i < code_buf_ptr; i++ ) writec(code_buf[i]);
codesize += code_buf_ptr;
}
if ( print_progress )
{
printf(" In : %ld bytes\n", textsize); /* Encoding is done. */
printf(" Out: %ld bytes\n", codesize);
printf(" Out/In: %.3f\n", (double)codesize / textsize);
}
DeInitTree();
return codesize;
}
///////////////////////////////////////////////////////////////////////////////////////
//
// Decompression code, cut & pasted from pre.cpp
//
///////////////////////////////////////////////////////////////////////////////////////
#define RINGBUFFERSIZE 4096 /* N size of ring buffer */
#define MATCHLIMIT 18 /* F upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length */
//#define WriteOut(x) {Dbg_MsgAssert(pOut<pIn,("Oops! Decompression overlap!\nIncrease IN_PLACE_DECOMPRESSION_MARGIN in sys\\file\\pip.cpp")); *pOut++ = x;}
#define WriteOut(x) {*pOut++ = x;}
#define USE_BUFFER 1 // we don't need no stinking buffer!!!!
#if USE_BUFFER
#ifdef __PLAT_NGPS__
// ring buffer is just over 4K 4096+17),
// so fits nicely in the PS2's 8K scratchpad
static unsigned char sTextBuf[RINGBUFFERSIZE + MATCHLIMIT - 1];
// Note: if we try to use the scratchpad, like this
// then the code actually runs slower
// if we want to optimize this, then it should
// be hand crafted in assembly, using 128bit registers
// const unsigned char * sTextBuf = (unsigned char*) 0x70000000;
#else
static unsigned char
sTextBuf[RINGBUFFERSIZE + MATCHLIMIT - 1]; /* ring buffer of size N,
with extra F-1 bytes to facilitate string comparison */
#endif
#endif
#define ReadInto(x) if (!Len) break; Len--; x = *pIn++
#define ReadInto2(x) Len--; x = *pIn++ // version that knows Len is Ok
// Decode an LZSS encoded stream
// Runs at approx 12MB/s on PS2 without scratchpad (which slows it down in C)
// a 32x CD would run at 4.8MB/sec, although we seem to get a lot less than this
// with our current file system, more like 600K per seconds.....
// Need to write a fast streaming file system....
// Ken: Made this return the new pOut so I can do some asserts to make sure it has
// written the expected number of bytes.
unsigned char *DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len) /* Just the reverse of Encode(). */
{
int i, j, k, r, c;
// uint64 LongWord;
// int bytes = 0;
// unsigned char *pScratch;
unsigned int flags;
// int basetime = (int) Tmr::ElapsedTime(0);
// int len = Len;
// int OutBytes = 4;
// int OutWord = 0;
#if USE_BUFFER
for ( i = 0; i < RINGBUFFERSIZE - MATCHLIMIT; i++ )
sTextBuf[i] = ' ';
r = RINGBUFFERSIZE - MATCHLIMIT;
#else
r = RINGBUFFERSIZE - MATCHLIMIT;
#endif
flags = 0;
for ( ; ; )
{
if ( ((flags >>= 1) & 256) == 0 )
{
ReadInto(c);
flags = c | 0xff00; /* uses higher byte cleverly */
} /* to count eight */
if ( flags & 1 )
{
ReadInto(c);
// putc(c, outfile);
WriteOut(c);
#if USE_BUFFER
sTextBuf[r++] = c;
r &= (RINGBUFFERSIZE - 1);
#else
r++;
// r &= (RINGBUFFERSIZE - 1); // don't need to wrap r until it is used
#endif
}
else
{
ReadInto(i);
ReadInto2(j); // note, don't need to check len on this one....
i |= ((j & 0xf0) << 4); // i is 12 bit offset
#if !USE_BUFFER
j = (j & 0x0f) + THRESHOLD+1; // j is 4 bit length (above the threshold)
unsigned char *pStream;
r &= (RINGBUFFERSIZE - 1); // wrap r around before it is used
pStream = pOut - r; // get base of block
if ( i>=r ) // if offset > r, then
pStream -= RINGBUFFERSIZE; // it's the previous block
pStream += i; // add in the offset to the base
r+=j; // add size to r
while ( j-- ) // copy j bytes
WriteOut(*pStream++);
#else
j = (j & 0x0f) + THRESHOLD; // j is 4 bit length (above the threshold)
for ( k = 0; k <= j; k++ ) // just copy the bytes
{
c = sTextBuf[(i+k) & (RINGBUFFERSIZE - 1)];
WriteOut(c);
sTextBuf[r++] = c;
r &= (RINGBUFFERSIZE - 1);
}
#endif
}
}
// int Time = (int) Tmr::ElapsedTime(basetime);
// if (Time > 5)
// {
// printf("decomp time is %d ms, for %d bytes, %d bytes/second\n", Time,len, len * 1000 /Time );
// }
return pOut;
}

12
Code/Core/compress.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef __CORE_COMPRESS_H
#define __CORE_COMPRESS_H
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
int Encode(char *pIn, char *pOut, int bytes_to_read, bool print_progress);
unsigned char *DecodeLZSS(unsigned char *pIn, unsigned char *pOut, int Len);
#endif

338
Code/Core/crc.cpp Normal file
View File

@ -0,0 +1,338 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: PS2 **
** **
** Module: Core **
** **
** File name: Core/crc.cpp **
** **
** Created by: 03/05/01 - spg **
** **
** Description: Crc functionality **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Crc
{
/*****************************************************************************
** Externals **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Private Types **
*****************************************************************************/
/*****************************************************************************
** Private Data **
*****************************************************************************/
static uint32 CRCTable[256] = // CRC polynomial 0xedb88320
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/*****************************************************************************
** Public Data **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Private Functions **
*****************************************************************************/
/*****************************************************************************
** Public Functions **
*****************************************************************************/
////////////////////////////////////////////////////////////////////////////////
// Generates a checksum from raw data, given pointer to that data, and the size
//
// input:
// const char *stream = pointer to data
// int size = number of bytes to CRC
//
// output:
// returns uint32 = checksum of the data
// if NULL pointer passed in, or zero size is given, then will return 0
//
uint32 GenerateCRCCaseSensitive( const char *stream, int size )
{
// A checksum of zero is used to mean no name.
if(( !stream ) || ( size <= 0 ))
{
return 0;
}
// Initializing the CRC to all one bits avoids failure of detection
// should entire data stream get cyclically bit-shifted by one position.
// The calculation of the probability of this happening is left as
// an exercise for the reader.
uint32 rc = 0xffffffff;
for (int i=0; i<size; i++)
{
rc = CRCTable[(rc^stream[i]) & 0xff] ^ ((rc>>8) & 0x00ffffff);
}
return rc;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// For use when calculating a total checksum of a bunch of chunks of data.
// Currently used when saving out the replay buffer to mem card.
uint32 UpdateCRC( const char *p_stream, int size, uint32 rc )
{
Dbg_MsgAssert(p_stream,("NULL p_stream"));
for (int i=0; i<size; i++)
{
rc = CRCTable[(rc^p_stream[i]) & 0xff] ^ ((rc>>8) & 0x00ffffff);
}
return rc;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Generates a checksum from a name, case insensitive.
uint32 GenerateCRC( const char *stream, int size )
{
// A checksum of zero is used to mean no name.
if(( !stream ) || ( size <= 0 ))
{
return 0;
}
// Initializing the CRC to all one bits avoids failure of detection
// should entire data stream get cyclically bit-shifted by one position.
// The calculation of the probability of this happening is left as
// an exercise for the reader.
uint32 rc = 0xffffffff;
for (int i=0; i<size; i++)
{
char ch=stream[i];
// Convert to lower case.
if (ch>='A' && ch<='Z')
{
ch='a'+ch-'A';
}
// Convert forward slashes to backslashes, otherwise two filenames which are
// effectively the same but with different slashes will give different checksums.
if (ch=='/')
{
ch='\\';
}
rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);
}
return rc;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
uint32 GenerateCRCFromString( const char *pName )
{
// A checksum of zero is used to mean no name.
if (!pName)
{
return 0;
}
// Initializing the CRC to all one bits avoids failure of detection
// should entire data stream get cyclically bit-shifted by one position.
// The calculation of the probability of this happening is left as
// an exercise for the reader.
uint32 rc = 0xffffffff;
const char *pCh=pName;
while (true)
{
char ch=*pCh++;
if (!ch)
{
break;
}
// Convert to lower case.
if (ch>='A' && ch<='Z')
{
ch='a'+ch-'A';
}
// Convert forward slashes to backslashes, otherwise two filenames which are
// effectively the same but with different slashes will give different checksums.
if (ch=='/')
{
ch='\\';
}
rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);
}
return rc;
}
// Same as above, but it's calculating the CRC of two strings added together
// but the first string is already CRCed
// essentially it's like jumping into GenerateGRCFromString halfway through
uint32 ExtendCRCWithString( uint32 rc, const char *pName )
{
if (!pName)
{
return rc;
}
const char *pCh=pName;
while (true)
{
char ch=*pCh++;
if (!ch)
{
break;
}
// Convert to lower case.
if (ch>='A' && ch<='Z')
{
ch='a'+ch-'A';
}
// Convert forward slashes to backslashes, otherwise two filenames which are
// effectively the same but with different slashes will give different checksums.
if (ch=='/')
{
ch='\\';
}
rc = CRCTable[(rc^ch) & 0xff] ^ ((rc>>8) & 0x00ffffff);
}
return rc;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
uint32 GetCRCTableEntry( int entry )
{
Dbg_Assert(( entry < 256 ) && ( entry >= 0 ));
return CRCTable[entry];
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Crc

73
Code/Core/crc.h Normal file
View File

@ -0,0 +1,73 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Crc (CRC) **
** **
** Created: 03/05/01 spg **
** **
** File name: core/crc.h **
** **
** Description: Crc Functionality **
** **
*****************************************************************************/
#ifndef __CORE_CRC_H
#define __CORE_CRC_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Crc
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
uint32 GenerateCRC( const char *stream, int size );
uint32 GenerateCRCCaseSensitive( const char *stream, int size );
uint32 UpdateCRC( const char *p_stream, int size, uint32 rc=0xffffffff );
uint32 GenerateCRCFromString( const char *pName );
uint32 ExtendCRCWithString( uint32 rc, const char *pName );
uint32 GetCRCTableEntry( int entry );
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Crc
#endif // __CORE_CRC_H

334
Code/Core/flags.h Normal file
View File

@ -0,0 +1,334 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Standard Header **
** **
** File name: core/flags.h **
** **
** Created: 10/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_FLAGS_H
#define __CORE_FLAGS_H
/*****************************************************************************
** Includes **
*****************************************************************************/
/*****************************************************************************
** Defines **
*****************************************************************************/
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
/************************************************************************
* *
* Class: flags *
* *
* Description: Template class for flags. *
* *
* *
***********************************************************************/
template < class _T >
class Flags
{
public:
Flags ( void );
Flags ( const uint val );
void ClearAll ( void );
void Clear ( _T flag_index );
void ClearMask ( const uint& f );
void Set ( _T flag_index, bool on = true );
void SetAll ( void );
void SetMask ( const uint& mask );
void SetVal ( const uint& f );
bool TestAny ( void ) const;
bool Test ( _T flag_index ) const;
bool TestMask ( const uint& mask ) const;
bool TestMaskAny ( const uint& mask ) const;
bool TestMaskAll ( const uint& mask ) const;
void Toggle ( _T flag_index );
operator uint (void) const;
Flags& operator= ( const Flags& src );
Flags& operator= ( const uint& val );
private:
uint flag;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
template < class _T > inline
Flags< _T >::Flags ( void )
: flag ( 0 )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Flags< _T >::Flags ( const uint val )
: flag ( val )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::ClearAll ( void )
{
flag = 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::Clear ( _T flag_index )
{
flag &= ~( 1 << static_cast< uint >( flag_index ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::ClearMask ( const uint& f )
{
flag &= ~f;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::Set ( _T flag_index, bool on )
{
if ( on )
{
flag |= ( 1 << static_cast< uint >( flag_index ));
}
else
{
flag &= ~( 1 << static_cast< uint >( flag_index ));
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::SetAll ( void )
{
flag = vUINT_MAX;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::SetMask ( const uint& mask )
{
flag |= mask;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::SetVal ( const uint& f )
{
flag = f;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Flags< _T >::TestAny ( void ) const
{
return ( flag != 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Flags< _T >::Test ( _T flag_index ) const
{
return (( flag & ( 1 << static_cast< uint >( flag_index ))) != 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Flags< _T >::TestMask ( const uint& mask ) const
{
return TestMaskAny(mask);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Flags< _T >::TestMaskAny ( const uint& mask ) const
{
return (( flag & mask ) != 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
bool Flags< _T >::TestMaskAll ( const uint& mask ) const
{
return (( flag & mask ) == mask );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
void Flags< _T >::Toggle ( _T flag_index )
{
flag ^= ( 1 << static_cast< uint >( flag_index ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Flags< _T >::operator uint (void) const
{
return flag;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Flags< _T >& Flags< _T >::operator= ( const Flags< _T >& src )
{
flag = static_cast< uint >( src.flag );
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
Flags< _T >& Flags< _T >::operator= ( const uint& val )
{
flag = val;
return *this;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
/*
template < class _T > inline
ostream& operator<< ( ostream& os, const Flags< _T >& src )
{
return os << static_cast< uint >( src );
}
*/
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_FLAGS_H

5
Code/Core/glue.h Normal file
View File

@ -0,0 +1,5 @@
#ifndef __GLUE_H__
#define __GLUE_H__
#endif // __GLUE_H__

11
Code/Core/log.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __CORE_DEBUG_LOG_H
#define __CORE_DEBUG_LOG_H
namespace Log
{
void Init();
void AddEntry(char *p_fileName, int lineNumber, char *p_functionName, char *p_message=NULL);
}
#endif // #ifndef __CORE_DEBUG_LOG_H

61
Code/Core/macros.h Normal file
View File

@ -0,0 +1,61 @@
/* Useful little macros...
Add any macros you want into this:
*/
#ifndef __USEFUL_LITTLE_MACROS_H__
#define __USEFUL_LITTLE_MACROS_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/support.h>
#define PERCENT_MULT ( ( 1.0f ) / 100.0f )
#define PERCENT( x, percent ) ( ( ( ( ( float )( x ) ) * ( ( float )( percent ) ) ) * PERCENT_MULT ) )
#define IPU (1.0f) // Inches per unit
#define INCHES(x) ((float)(x))
#define INCHES_PER_SECOND(x) ((float)(x))
#define INCHES_PER_SECOND_SQUARED(x) ((float)(x))
#define FEET_TO_INCHES( x ) ( x * 12.0f )
#define FEET(x) ((float)(x*12.0f))
#define FEET_PER_MILE 5280.0f
#define MPH_TO_INCHES_PER_SECOND( x ) ( ( ( x ) * FEET_PER_MILE * 12.0f ) / ( 60.0f * 60.0f ) )
#define MPH_TO_IPS( x ) MPH_TO_INCHES_PER_SECOND( x )
#define INCHES_PER_SECOND_TO_MPH( x ) ( ( x ) / 12.0f / FEET_PER_MILE * 60.0f * 60.0f )
#define IPS_TO_MPH( x ) INCHES_PER_SECOND_TO_MPH( x )
#define RADIANS_PER_SECOND_TO_RPM( x ) (9.5496f * ( x ))
#define RPM_TO_RADIANS_PER_SECOND( x ) (0.10472f * ( x ))
#define DEGREES_TO_RADIANS( x ) ( ( x ) * ( 2.0f * Mth::PI / 360.0f ) )
#define RADIANS_TO_DEGREES( x ) ( ( x ) / ( DEGREES_TO_RADIANS( 1.0f ) ) )
#define THE_NUMBER_OF_THE_BEAST 666
// Takes screen coordinates in 'default' screen space - 640x448 - and converts them based on PAL and system defines.
// Convert from logical to SCREEN coordinates
#ifdef __PLAT_XBOX__
// Unfortunately, this has to be a platform-specific macro, since it references Xbox specific global structures to determine
// the width and height of the back buffer.
#include <gfx/xbox/nx/nx_init.h>
#define SCREEN_CONV_X( x ) ((( x ) * NxXbox::EngineGlobals.screen_conv_x_multiplier ) + NxXbox::EngineGlobals.screen_conv_x_offset )
#define SCREEN_CONV_Y( y ) ((( y ) * NxXbox::EngineGlobals.screen_conv_y_multiplier ) + NxXbox::EngineGlobals.screen_conv_y_offset )
#else
#define SCREEN_CONV_X( x ) (Config::GetHardware()==Config::HARDWARE_XBOX ? (int)((( x ) * ( 640.0f / 704.0f )) + 32 ) : Config::PAL() ? (( x ) * 512 ) / 640 : (x) )
#define SCREEN_CONV_Y( y ) (Config::GetHardware()==Config::HARDWARE_XBOX ? (( y ) + 16 ) : Config::PAL() ? (( y ) * 512 ) / 448 : (y) )
#endif // __PLAT_XBOX__
// Convert from screen to LOGICAL coordinates
#define LOGICAL_CONV_X( x ) (Config::GetHardware()==Config::HARDWARE_XBOX ? (x) : Config::PAL() ? (( x ) * 640 ) / 512 : (x) )
#define LOGICAL_CONV_Y( y ) (Config::GetHardware()==Config::HARDWARE_XBOX ? (y) : Config::PAL() ? (( y ) * 448 ) / 512 : (y) )
#endif // __USEFUL_LITTLE_MACROS_H__

68
Code/Core/math.h Normal file
View File

@ -0,0 +1,68 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Math (MTH) **
** **
** File name: core/math.h **
** **
** Created: 11/23/99 - mjb **
** **
** Description: Math Library **
** **
*****************************************************************************/
#ifndef __CORE_MATH_H
#define __CORE_MATH_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <math.h>
// The following overlaoded functions will make sure that if you accidently call a double version of
// a trig function with a float argument, then it will simply call the float version
// (double precision is very very slow on the PS2)
#ifndef __PLAT_XBOX__
inline float acos( float x ) {return acosf( x );}
inline float asin( float x ) {return asinf( x );}
inline float atan( float x ) {return atanf( x );}
inline float atan2( float x, float y){return atan2f( x , y );}
inline float cos( float x ) {return cosf( x );}
inline float sin( float x ) {return sinf( x );}
inline float tan( float x ) {return tanf( x );}
inline float fabs( float x ) {return fabsf( x );}
#endif // ifndef __PLAT_XBOX__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/support.h>
#include <core/math/math.h>
#include <core/math/vector.h>
#include <core/math/matrix.h>
#include <core/math/quat.h> // need quat.h before matrix, but after vector (for the GetScalar function)
#include <core/math/vector.inl>
#include <core/math/matrix.inl>
#include <core/math/quat.inl>
#include <core/math/rect.h>
/******************************************************************/
/* */
/* */
/******************************************************************/
#endif // __CORE_MATH_H

365
Code/Core/singleton.h Normal file
View File

@ -0,0 +1,365 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 2000 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Template Singleton class **
** **
** File name: core/singleton.h **
** **
** Created: 10/17/00 - mjb **
** **
** **
*****************************************************************************/
#ifndef __CORE_SINGLETON_H
#define __CORE_SINGLETON_H
/*
Singletons
(Documentation by Mick)
A singleton is a single instance of a class which is dynamically
allocated just once.
To make a class such as CStats a singleton class, you do this:
class CStats
{
// Normal Class definition goes here...
...
// Constructor and destructor MUST BE PRIVATE, for it to be a singleton
private:
CStats( void );
~CStats( void );
// Macro to include the singleton code
DeclareSingletonClass( CStats );
}
This macro just places some static functions in the class, and a static pointer to
the single instance of class itself (initially NULL)
You can then initialize the singleton by the line
Spt::SingletonPtr< CStats > p_stats( true );
This is somewhere at a high level in the code (currently they are all in main())
The original design of our singletons had in mind that there would be reference counting
of the references tot he singleton, and when it was no longer referenced, it would
delete itself. So, in many places in the code, the singletons are reference by creating a
"Spt::SingletonPtr", which is a smart pointer to the instance of the singleton.
For example:
Spt::SingletonPtr< CStats > p_stats;
p_stats->Update();
In the ultimate version of this idea, the game would be comprised of many modules,
systems and subsystems. Each would be a singleton. Each could be dependent on
other singletons, but more that one module could depend on a particular singleton,
so you coudl not rely on a module to de-initialize the singletons it needed
as they might be needed elsewhere.
So, each module would include a Spt::SingletonPtr for each of the modules that it
needed, so when a module was created it would increase the reference on the singletons
and create any that did not exists. Then when it shut down, the pointers would automatically
go out of scope, and any singleton that was not referenced would automatically be deleted,
so there would never be more systems active than there needed to be.
However, it turned out that this was generally overkill. Most systems were initialized at the start,
and those that were not, we wanted to have control over the initialization of them.
The use of smart pointers here also obfuscated the code, and introduced a significant
execution overhead that was totally unnecessary.
So, the prefered method to access a singleton now is:
CStats::Instance()->Update();
This simply references the instance directly (as it's inline), and so
does no addition processing. It's easier to type as well.
*/
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/support.h>
#ifndef __SYS_MEM_MEMPTR_H
#include <sys/mem/memptr.h>
#endif
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Spt
{
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
template< class _T >
class SingletonPtr : public Spt::Class
{
public:
SingletonPtr( bool create = false );
virtual ~SingletonPtr( void );
#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
SingletonPtr( const SingletonPtr< _T > & rhs );
SingletonPtr< _T >& operator= ( const SingletonPtr< _T >& rhs );
#else
template < class _NewT > // template copy contructor
SingletonPtr( const SingletonPtr< _NewT >& rhs ); // needed to support inheritance correctly
template < class _NewT >
SingletonPtr< _T >& operator= ( const SingletonPtr< _NewT >& rhs ); // template assignment operator
#endif
_T* operator-> () const;
_T& operator* () const;
private:
Mem::Ptr< _T > mp_instance;
};
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
SingletonPtr< _T >::SingletonPtr( bool create )
: mp_instance ( _T::sSgltnInstance( create ) )
{
#ifdef __NOPT_FULL_DEBUG__
SetName( const_cast< char* >( sClassNode()->GetName() ));
#endif
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
SingletonPtr< _T >::~SingletonPtr()
{
mp_instance->sSgltnDelete();
}
#if ( defined ( __PLAT_XBOX__ ) || defined ( __PLAT_WN32__ ))
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
SingletonPtr< _T >::SingletonPtr ( const SingletonPtr< _T >& rhs )
: mp_instance ( _T::sSgltnInstance() )
{
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
SingletonPtr< _T >& SingletonPtr< _T >::operator= ( const SingletonPtr< _T >& rhs )
{
return *this;
}
#else
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > template < class _NewT > inline
SingletonPtr< _T >::SingletonPtr< _T >( const SingletonPtr< _NewT >& rhs )
: mp_instance ( _NewT::sSgltnInstance() )
{
Dbg_MsgAssert( false,( "Microsoft VC++ sucks - don't do this (yet)" ));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > template < class _NewT > inline
SingletonPtr< _T >& SingletonPtr< _T >::operator= ( const SingletonPtr< _NewT >& rhs )
{
Dbg_MsgAssert( false,( "Microsoft VC++ sucks - don't do this (yet)" ));
return *this;
}
#endif
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_T* SingletonPtr< _T >::operator-> () const
{
return mp_instance.Addr();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
template < class _T > inline
_T& SingletonPtr< _T >::operator* () const
{
return *mp_instance;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
#define DeclareSingletonClass(_T) \
private: \
static _T* sSgltnInstance( bool create = false ); \
static void sSgltnDelete( void ); \
\
static _T* sp_sgltn_instance; \
static uint s_sgltn_count; \
public: \
inline static void Create(void) {sp_sgltn_instance = new _T;} \
inline static _T* Instance(void) {return sp_sgltn_instance;} \
inline bool Initilized(void) {return (sp_sgltn_instance!=NULL);} \
\
friend class Spt::SingletonPtr< _T >; \
#define DefinePlacementSingletonClass(_T, _P, _N ) \
\
_T* _T::sp_sgltn_instance = NULL; \
uint _T::s_sgltn_count = 0; \
\
_T* _T::sSgltnInstance( bool create ) \
{ \
\
\
if ( !sp_sgltn_instance && create ) \
{ \
sp_sgltn_instance = new (_P) _T; \
} \
\
Dbg_AssertType( sp_sgltn_instance, _T ); \
\
++s_sgltn_count; \
return sp_sgltn_instance; \
} \
\
void _T::sSgltnDelete( void ) \
{ \
\
\
Dbg_MsgAssert(( s_sgltn_count > 0 ),( "Reference count imbalance" )); \
\
if ( s_sgltn_count > 1 ) \
{ \
s_sgltn_count--; \
return; \
} \
\
delete sp_sgltn_instance; \
sp_sgltn_instance = NULL; \
s_sgltn_count = 0; \
} \
#define DefineSingletonClass(_T,_N) \
DefinePlacementSingletonClass(_T, (Mem::Allocator*)NULL, _N )
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
/*****************************************************************************
** Macros **
*****************************************************************************/
} // namespace Spt
#endif // __CORE_SINGLETON_H

40
Code/Core/support.h Normal file
View File

@ -0,0 +1,40 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: Core Library **
** **
** Module: Support (SPT) **
** **
** File name: core/support.h **
** **
** Created: 05/27/99 - mjb **
** **
*****************************************************************************/
#ifndef __CORE_SUPPORT_H
#define __CORE_SUPPORT_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/support/class.h>
#include <core/support/support.h>
#include "sk/language.h"
/*****************************************************************************
** Defines **
*****************************************************************************/
// #define PAL for PAL mode build.
#define PALx
#endif // __CORE_TASK_H

32
Code/Core/thread.h Normal file
View File

@ -0,0 +1,32 @@
/*******************************************************************
*
* DESCRIPTION: thread.h
*
* AUTHOR: JAB
*
* HISTORY:
*
* DATE:9/1/2000
*
*******************************************************************/
/** include files **/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#ifdef __PLAT_WN32__
#else
# ifdef __PLAT_XBOX__
# else
# ifdef __PLAT_NGPS__
# include "thread/ngps/t_thread.h"
# elif defined( __PLAT_NGC__ )
# include "thread/ngc/t_thread.h"
# else
# error Unsupported Platform
# endif
# endif
#endif

147
Code/GameFlow.txt Normal file
View File

@ -0,0 +1,147 @@
Flow of control
=====================================
"autolaunch level=Load_Sch game=career"
script autolaunch
script request_level level=<level>
ScriptRequestLevel
-set Skate::m_requested_level
script cleanup_before_loading_level
ScriptCleanup
-skate_mod->Cleanup( )
-skate_mod->GetGoalManager()->RemoveAllGoals()
-particle_manager->DestroyAllSystems();
-ParticleFX::BloodSplatDestroy();
-SkateScript::ClearNodeNameHashTable();
-ParticleFX::DestroyTerrainEffectProperties();
-gfx_man->DisableFog();
-Script::KillStoppedScripts();
-sk3_sfx_manager->Reset( );
-sfx_manager->CleanUp( );
-ass_manager->UnloadAllTables( );
-Script::CSymbolTableEntry *p_sym=Script::LookUpSymbol("NodeArray");
-if (p_sym)
SkateScript::UnloadQB(p_sym->mSourceFileNameChecksum);
-SkateScript::UnloadQB(s_level_specific_qb);
-ScriptUnloadAllLevelGeometry(NULL,NULL);
-skate_mod->UnloadSkaters();
-Mem::Manager::sHandle().DeleteSkaterHeaps();
script load_requested_level level=load_sch
script LoadLevel
script PreLevelLoad
-does nothing
ScriptLaunchLevel level=load_sch
-Skate::OpenLevel()
-Script::RunScript(level_script);
script Load_Sch
script load_level level_sch
-see below....
PostLevelLoad
-does nothing
gameflow StandardGameFlow
skate_mod->mp_gameFlow->Reset( ScriptChecksum )
-set m_requestedScript
Later...
CGameFlow::Update()
GameFlow_Startup
-reset panel, sound stuff
-maybe enter free skate in network game
-choose game mode
-Put skaters in world
-Set screen mode
-Run intro script
-repeat:
GameFlow_StartRun
GameFlow_PlayRun
GameFlow_WaitEnd
-and other shit
=====================================
-----------------------
"load_level level_sch"
Level_Sch = {
loading_screen = "loadscrn_generic"
pre = "sch.pre"
scnpre = "schscn.pre"
Level = "sch"
Sky = "sf2_Sky"
qb = "levels\sch\sch.qb"
colpre = "schcol.pre"
level_qb = "levels\sch\sch_scripts.qb"
startup_script = sch_Startup
default_stats = 5
}
Level_Sk4Ed = {
loading_screen = "loadscrn_generic"
pre = "sk4ed.pre"
scnpre = "sk4edscn.pre"
Level = "sk4ed"
Sky = "can_Sky"
qb = "levels\sk4ed\sk4ed.qb"
colpre = "sk4edcol.pre"
level_qb = "levels\sk4ed\sk4ed_scripts.qb"
startup_script = Sk4Ed_Startup
default_stats = 8
level_number = LevelNum_Lon
park_editor
}
-----------------------
script load_level level_sch
DisplayLoadingScreen <loading_screen>
*** Park editor yes ***
script LoadLevelPreFile <scnpre>
ScriptLoadPreFile
*** Park editor, need special flag ***
ScriptLoadScene scene=<level> (for sky, then world)
Nx::CTexDictManager::sLoadTextureDictionary(p_scene_name)
Nx::CEngine::sLoadScene(p_scene_name, p_tex_dict);
ScriptUnloadPreFile
*** Park editor maybe ***
script LoadLevelPreFile <colpre>
ScriptLoadCollision scene=<level>
p_scene->LoadCollision(p_scene_name)
ScriptUnloadPreFile
*** Park editor yes ***
script LoadLevelPreFile <pre>
ScriptLoadQB <level_qb>
SkateScript::LoadQB
Script::LoadQB
-load it into memory
ParseQB()
-restart all scripts referring to symbols
-do symbol table processing
-do following just for NodeArray symbol
- can reference nodes by name or prefix
CreateNodeNameHashTab
GeneratePrefixInfo();
*** don't call ScriptParseNodeArray for park editor, I don't think ***
*** duplicate some functionality ***
ScriptLoadNodeArray <qb>
SkateScript::LoadQB (see above)
ScriptParseNodeArray
-does a lot of stuff...
LoadTerrain
-doesn't seem to exist
CC_Startup
-loads some test camera stuff
run <startup_script> (sch_startup)
ScriptUnloadPreFile

898
Code/Gel/AssMan/AssMan.cpp Normal file
View File

@ -0,0 +1,898 @@
//****************************************************************************
//* MODULE: Gel/AssMan
//* FILENAME: AssMan.cpp
//* OWNER: Matt Duncan
//* CREATION DATE: 11/17/2000
//****************************************************************************
// start autoduck documentation
// @DOC Assman
// @module Assman | None
// @subindex Scripting Database
// @index script | Assman
/*
Assets are generally binary files that are processed in some way when loaded
(although they might simply be loaded).
They are always referenced by the 32-bit checksum of the name of the file
Design and art guidelines already require that all filenames in the project
are unique names.
The asset manager should handle generic assets... (it shouldn't need
to know anything about texture dictionaries or clumps or anims...)
*/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <gel/assman/assman.h>
#include <core/singleton.h>
#include <core/string/stringutils.h>
#include <sys/file/AsyncFilesys.h>
#include <gel/assman/assettypes.h>
#include <gel/assman/animasset.h>
#include <gel/assman/cutsceneasset.h>
#include <gel/assman/skeletonasset.h>
#include <gel/assman/skinasset.h>
#include <gel/assman/refasset.h>
#include <gel/assman/nodearrayasset.h>
#include <gel/scripting/checksum.h>
#include <gel/scripting/script.h>
#include <gel/scripting/struct.h>
#include <gel/scripting/symboltable.h>
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Ass
{
DefineSingletonClass( CAssMan, "Shared Asset Manager" );
struct SAssetLookup
{
char* p_extension;
EAssetType type;
};
static SAssetLookup s_asset_lookup[] =
{
{"BIN", ASSET_BINARY},
{"CLD", ASSET_COLLISION},
{"SCN", ASSET_SCENE},
{"MDL", ASSET_SKIN},
{"SKA", ASSET_ANIM},
{"FAM", ASSET_ANIM}, // facial anims
{"SKE", ASSET_SKELETON},
{"SKIN", ASSET_SKIN},
{"TEX", ASSET_TEXTURES},
{"CUT", ASSET_CUTSCENE},
{"QB", ASSET_NODEARRAY},
// Insert new types above this line
{NULL, ASSET_UNKNOWN} // terminator;
};
/*****************************************************************************
** Public Functions **
*****************************************************************************/
/******************************************************************/
/* */
/* */
/******************************************************************/
CAssMan::CAssMan()
{
mp_asset_table = new Lst::HashTable<Ass::CAsset>( 10 );
// for debugging
mp_assetlist_head = new CAsset;
mp_assetlist_head->SetText("Asset List Head (Possible error here?)");
mp_assetlist_head->mp_next = mp_assetlist_head;
mp_assetlist_head->mp_prev = mp_assetlist_head;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CAssMan::~CAssMan()
{
UnloadAllTables( true );
delete mp_asset_table;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
EAssetType CAssMan::FindAssetType( const char *p_assetName )
{
// given a file name, then find the type of asset that this represents
// the asset type is determined by the file extension
// so first, find the last . in the assetName
const char *p_ext = p_assetName + strlen(p_assetName);
while ( p_ext > p_assetName && *p_ext != '.' )
{
p_ext--;
}
if ( *p_ext != '.' )
{
return ASSET_UNKNOWN;
}
p_ext++;
// p_ext now points to the extension for the file name
SAssetLookup *p_lookup = &s_asset_lookup[0];
while ( p_lookup->p_extension != NULL )
{
// note, ignoring case
if ( strcmpi( p_lookup->p_extension, p_ext ) == 0 )
{
return p_lookup->type;
}
p_lookup++;
}
return ASSET_UNKNOWN;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::LoadAssetFromStream(uint32 asset_name, uint32 asset_type, uint32* p_data, int data_size, bool permanent, uint32 group)
{
// Note: There's no reason to support async loads when
// loading an asset from a data stream...
// load an asset, and return a pointer to the asset data
// given an asset name checksum, find the type of the asset, and then load it
Dbg_MsgAssert(!AssetAllocated(asset_name),("Asset %08x already loaded",asset_name));
CAsset* p_asset = NULL;
// based on the asset type, create an asset of the correct type
switch (asset_type)
{
case ASSET_ANIM:
p_asset = new CAnimAsset;
break;
case ASSET_SKIN:
p_asset = new CSkinAsset;
break;
default:
// right now, the only file type that's supported
// for data streams is the "cutscene model"
Dbg_MsgAssert(0,("Asset %08x is of unsupported type %d",asset_name,asset_type));
}
p_asset->m_permanent = permanent;
p_asset->m_group = group;
p_asset->m_dead = false; // it is not dead
// fake an asset name for debugging
char pDebugAssetString[256];
sprintf( pDebugAssetString, "%08x from data stream", asset_name );
p_asset->SetText(pDebugAssetString);
// finally, call the asset's Load member function to load it
int error = p_asset->Load(p_data, data_size);
if ( error != 0 )
{
if ( Script::GetInteger( CRCD(0x25dc7904,"AssertOnMissingAssets") ) )
{
Dbg_MsgAssert(0,("Loading asset %08x returned error %d",asset_name,error));
}
else
{
delete p_asset;
p_asset = NULL;
}
return NULL;
}
else
{
// only add it to the table once we're sure there's no error
uint32 checksum = asset_name;
Dbg_MsgAssert(!mp_asset_table->GetItem( checksum ),("Asset %08x already in table",asset_name));
mp_asset_table->PutItem( checksum, p_asset);
p_asset->SetID(checksum);
// link in at the end, so things are added in order
p_asset->mp_next = mp_assetlist_head;
p_asset->mp_prev = mp_assetlist_head->mp_prev;
mp_assetlist_head->mp_prev->mp_next = p_asset;
mp_assetlist_head->mp_prev = p_asset;
Dbg_MsgAssert(mp_asset_table->GetItem( checksum ) == p_asset,("Asset does not match entry in table"));
Dbg_Assert( p_asset );
return p_asset->GetData();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::LoadAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent, uint32 group, void* pExtraData, Script::CStruct *pParams)
{
// load an asset, and return a pointer to the asset data
// given an asset filename, find the type of the asset, and then load it
Dbg_MsgAssert(!AssetAllocated(p_assetName),("Asset %s already loaded",p_assetName));
CAsset * p_asset = NULL;
// Find the asset type
EAssetType asset_type = FindAssetType(p_assetName);
Dbg_MsgAssert(asset_type != ASSET_UNKNOWN,("Asset %s is of unknown type",p_assetName));
// based on that, create an asset of the correct type
switch (asset_type)
{
case ASSET_ANIM:
p_asset = new CAnimAsset;
break;
case ASSET_SKELETON:
p_asset = new CSkeletonAsset;
break;
case ASSET_SKIN:
p_asset = new CSkinAsset;
break;
case ASSET_CUTSCENE:
p_asset = new CCutsceneAsset;
break;
case ASSET_NODEARRAY:
p_asset = new CNodeArrayAsset;
break;
case ASSET_SCENE:
case ASSET_TEXTURES:
case ASSET_COLLISION:
case ASSET_BINARY:
default:
Dbg_MsgAssert(0,("Asset %s is of unsupported type %d",p_assetName,asset_type));
}
p_asset->m_permanent = permanent;
p_asset->m_group = group;
p_asset->m_dead = false; // it is not dead
p_asset->SetText(p_assetName); // record asset name for debugging
// Garrett: Make sure that we only set async on the things that can handle them
if (async_load)
{
Dbg_MsgAssert(asset_type == ASSET_ANIM, ("Can't load this asset type asynchronously: %d", asset_type));
}
// finally, call the asset's Load member function to load it
int error = p_asset->Load(p_assetName, async_load, use_pip, pExtraData, pParams);
if ( error != 0 )
{
if ( Script::GetInteger( CRCD(0x25dc7904,"AssertOnMissingAssets") ) )
{
Dbg_MsgAssert(0,("Loading asset %s returned error %d",p_assetName,error));
}
else
{
delete p_asset;
p_asset = NULL;
}
return NULL;
}
else
{
// only add it to the table once we're sure there's no error
uint32 checksum = Script::GenerateCRC( p_assetName );
Dbg_MsgAssert(!mp_asset_table->GetItem( checksum ),("Asset %s already in table",p_assetName));
mp_asset_table->PutItem( checksum, p_asset);
p_asset->SetID(checksum);
// link in at the end, so things are added in order
p_asset->mp_next = mp_assetlist_head;
p_asset->mp_prev = mp_assetlist_head->mp_prev;
mp_assetlist_head->mp_prev->mp_next = p_asset;
mp_assetlist_head->mp_prev = p_asset;
Dbg_MsgAssert(mp_asset_table->GetItem( Script::GenerateCRC( p_assetName )) == p_asset,("Asset does not match entry in table"));
Dbg_Assert( p_asset );
return p_asset->GetData();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::GetFirstInGroup( uint32 group )
{
// return the first asset in the asset manager that is in this group
// will return NULL if there are none of teh specified group
return GetNthInGroup(group,0);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::GetNthInGroup( uint32 group, int n )
{
// return the nth asset in the asset manager that is in this group
// will return NULL if there are none of the specified group
CAsset* p_asset = mp_assetlist_head->mp_next;
while (p_asset != mp_assetlist_head)
{
// printf ("%d: Checkingfor %x, group = %x\n",n,group,p_asset->m_group);
CAsset *p_next = p_asset->mp_next;
if (p_asset->m_group == group)
{
// printf ("%d: GROUP MATCH %x, group = %x\n",n,group,p_asset->m_group);
if (n==0)
{
// printf ("%d: COUNT MATCH %x, group = %x\n",n,group,p_asset->m_group);
return p_asset->GetData();
}
n--;
}
p_asset = p_next;
}
return NULL;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAssMan::GetGroup(uint32 checksum)
{
CAsset* p_actual = mp_asset_table->GetItem(checksum);
Dbg_MsgAssert(p_actual, ("GetIndexInGroup with asset not found\n"));
return p_actual->GetGroup();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAssMan::GetIndexInGroup(uint32 checksum)
{
// find this entry, and see which number it is in the group
// i.e, returns the intex into the group
CAsset* p_actual = mp_asset_table->GetItem(checksum);
Dbg_MsgAssert(p_actual, ("GetIndexInGroup with asset not found\n"));
int n = 0; // index starts at 0
CAsset* p_asset = mp_assetlist_head->mp_next;
while (p_asset != mp_assetlist_head)
{
CAsset *p_next = p_asset->mp_next;
if (p_asset == p_actual)
{
return n; // if we've found it, then return the asset
}
if (p_asset->m_group == p_actual->m_group) // if in same group
{
n++; // increment index
}
p_asset = p_next;
}
Dbg_MsgAssert(0, ("ERROR IN GetIndexInGroup\n"));
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAssMan::CountGroup(uint32 group)
{
int n = 0; // index starts at 0
CAsset* p_asset = mp_assetlist_head->mp_next;
while (p_asset != mp_assetlist_head)
{
CAsset *p_next = p_asset->mp_next;
if (p_asset->m_group == group) // if in same group
{
n++; // increment index
}
p_asset = p_next;
}
return n;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAssMan::CountSameGroup(uint32 checksum)
{
// a utility function to count the assets in the same group as another asset
return CountGroup(GetGroup(checksum));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::DestroyReferences( CAsset* pAsset )
{
// Destroys an asset's references
Dbg_Assert( pAsset );
while (pAsset->mp_ref_asset)
{
// destroying a reference is similar to an asset, except we
// do not need to call unload
// printf ("Deleting Reference %p of type %d, <%s>, <%s>\n",p_asset->mp_ref_asset,p_asset->mp_ref_asset->GetType(),p_asset->mp_ref_asset->Name(), p_asset->mp_ref_asset->GetText());
uint32 id = pAsset->mp_ref_asset->m_id;
pAsset->mp_ref_asset->Unlink();
delete pAsset->mp_ref_asset;
mp_asset_table->FlushItem(id);
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::UnloadAsset( CAsset* pAsset )
{
// Unload an asset and delete it
// note the current pairing of create/load, and unload/delete
// in the future, we might need to seperate them out into two distinct stages
Dbg_Assert( pAsset );
uint32 id = pAsset->m_id;
Dbg_MsgAssert(pAsset->LoadFinished(), ("UnloadAsset(): Asset not finished loading"));
pAsset->Unlink();
pAsset->Unload();
delete pAsset;
mp_asset_table->FlushItem(id);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::ReloadAsset( uint32 assetID, const char* pFileName, bool assertOnFail )
{
Ass::CAsset* pAsset;
pAsset = this->GetAssetNode( assetID, assertOnFail );
if ( pAsset )
{
Dbg_MsgAssert(pAsset->LoadFinished(), ("ReloadAsset(): Asset not finished loading"));
return pAsset->Reload( pFileName );
}
else
{
return false;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CAsset* CAssMan::GetAssetNode( uint32 assetID, bool assertOnFail )
{
CAsset *p_asset = mp_asset_table->GetItem(assetID);
if ( assertOnFail )
{
Dbg_MsgAssert(p_asset, ("Asset Not found <%s>", Script::FindChecksumName(assetID)));
//Dbg_MsgAssert(p_asset->LoadFinished(), ("Asset not finished loading (%s)", Script::FindChecksumName(assetID)));
}
// Don't return pointer if it isn't done loading
if ( p_asset && !p_asset->LoadFinished() )
{
//p_asset = NULL;
// Wait if not done loading
while (!p_asset->LoadFinished())
{
Dbg_Message("Waiting for async asset load to finish...");
File::CAsyncFileLoader::sWaitForIOEvent(false);
}
}
return p_asset;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::GetAsset(uint32 assetID, bool assertOnFail )
{
// Return a pointer to the asset data, or NULL if not found
CAsset *p_asset = mp_asset_table->GetItem(assetID);
if (p_asset /*&& p_asset->LoadFinished()*/)
{
// Wait if not done loading
while (!p_asset->LoadFinished())
{
Dbg_Message("Waiting for async asset load to finish...");
File::CAsyncFileLoader::sWaitForIOEvent(false);
}
void *p_asset_data = p_asset->GetData();
Dbg_MsgAssert(p_asset_data,("Asset has no data"));
return p_asset_data;
}
else
{
if ( assertOnFail )
{
Dbg_MsgAssert(p_asset, ("Asset 0x%x Not found (%s)",assetID,Script::FindChecksumName(assetID)));
//Dbg_MsgAssert(p_asset->LoadFinished(), ("Asset 0x%x not finished loading (%s)",assetID,Script::FindChecksumName(assetID)));
}
return NULL;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::GetAsset(const char *p_assetName, bool assertOnFail)
{
//returns a pointer to the asset data, does not load it if not found
if ( assertOnFail )
{
Dbg_MsgAssert(AssetAllocated(p_assetName),("asset %s is not loaded in GetAsset",p_assetName));
}
void *p_asset_data = GetAsset(Script::GenerateCRC( p_assetName ), assertOnFail );
if ( assertOnFail )
{
Dbg_MsgAssert(p_asset_data,("Asset has NULL data %s",p_assetName));
}
return p_asset_data;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void* CAssMan::LoadOrGetAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent, uint32 group, void* pExtraData, Script::CStruct * pParams)
{
//returns a pointer to the asset data, and loads the asset if not found
void *p_asset_data;
CAsset *p_asset = mp_asset_table->GetItem(Script::GenerateCRC( p_assetName ));
if (p_asset)
{
p_asset_data = p_asset->GetData();
Dbg_MsgAssert(p_asset_data,("Asset has NULL data %s",p_assetName));
//Dbg_MsgAssert(p_asset->LoadFinished(), ("Asset not finished loading (%s)", p_assetName));
// Wait if not done loading
while (!p_asset->LoadFinished())
{
Dbg_Message("Waiting for async asset load to finish...");
File::CAsyncFileLoader::sWaitForIOEvent(false);
}
}
else
{
p_asset_data = LoadAsset(p_assetName, async_load, use_pip, permanent, 0, pExtraData,pParams);
}
if ( Script::GetInteger( CRCD(0x25dc7904,"AssertOnMissingAssets") ) )
{
// do some extra checks here if we're asserting on missing assets
Dbg_MsgAssert(p_asset_data,("Could not load asset %s",p_assetName));
Dbg_MsgAssert(AssetAllocated(p_assetName),("asset %s is not loaded after LoadOrGetAsset",p_assetName));
}
return p_asset_data;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::AssetAllocated(uint32 assetID)
{
// Return true if the asset has at least started loading
return (NULL != mp_asset_table->GetItem(assetID));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::AssetAllocated(const char *p_assetName)
{
// Return true if the asset has at least started loading
return (AssetAllocated(Script::GenerateCRC( p_assetName )));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::AssetLoaded(uint32 assetID)
{
// Return true if the asset is done loading
CAsset *p_asset = mp_asset_table->GetItem(assetID);
if (p_asset && p_asset->LoadFinished())
{
return true;
}
else
{
return false;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::AssetLoaded(const char *p_assetName)
{
// Return true if the asset is done loading
return (AssetLoaded(Script::GenerateCRC( p_assetName )));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::AddRef(uint32 asset_id, uint32 ref_id, uint32 group)
{
// Add a reference to an asset, so we can access it via a new id
Dbg_MsgAssert(AssetAllocated(asset_id),("Adding ref to unloaded asset\n"));
CAsset *p_asset = new CRefAsset(mp_asset_table->GetItem(asset_id));
Dbg_MsgAssert(!mp_asset_table->GetItem( ref_id ),("ref already in table/n"));
mp_asset_table->PutItem( ref_id, p_asset);
p_asset->SetID(ref_id);
p_asset->SetGroup(group);
// link it to the end of the list
p_asset->mp_next = mp_assetlist_head;
p_asset->mp_prev = mp_assetlist_head->mp_prev;
mp_assetlist_head->mp_prev->mp_next = p_asset;
mp_assetlist_head->mp_prev = p_asset;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::AddRef(const char *p_assetName, uint32 ref_id, uint32 group)
{
Dbg_MsgAssert(!mp_asset_table->GetItem( ref_id ),("ref %lx already in table\nwhen adding to %s\n",ref_id,p_assetName));
Dbg_MsgAssert(AssetAllocated(p_assetName),("Adding ref to unloaded asset %s\n",p_assetName));
uint32 checksum = Script::GenerateCRC( p_assetName );
AddRef(checksum,ref_id, group);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::UnloadAllTables( bool destroy_permanent )
{
// printf ( "Unloading all tables" );
CAsset* p_asset;
p_asset = mp_assetlist_head->mp_next;
while (p_asset != mp_assetlist_head)
{
CAsset *p_next = p_asset->mp_next;
if ( destroy_permanent || !p_asset->m_permanent )
{
// First destroy any references to this asset
DestroyReferences( p_asset );
// Need to update p_next, in case it was change by destroying above code
p_next = p_asset->mp_next;
UnloadAsset( p_asset );
}
p_asset = p_next;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::SetDefaultPermanent(bool permanent)
{
// set the default permanent state of loaded assets
// (generally this will be false)
m_default_permanent = permanent;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::GetDefaultPermanent() const
{
return m_default_permanent;
}
// The following functions are kind of kludge for referencing anims
// Ideally, I'd like to remove these kludges and simplify the
// asset manager
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAssMan::LoadAnim(const char* pFileName, uint32 animName, uint32 referenceChecksum, bool async_load, bool use_pip)
{
// If the asset was previously loaded, then we are just creating a reference to it
// so the m_permanent flag should be set based on m_default_permanent, and NOT INHERITED
if (AssetAllocated(pFileName))
{
// if descChecksum was supplied, then adding a reference
if (animName && !AssetAllocated(animName + referenceChecksum))
{
// adding a reference
AddRef(pFileName, animName + referenceChecksum, referenceChecksum);
// the m_permanent will have been inherited from the parent asset
// Now get the reference asset, and set the permanent flag to m_defualt_permanet
CAsset *p_asset = mp_asset_table->GetItem(animName + referenceChecksum);
Dbg_MsgAssert(p_asset,("(Mick) Error re-getting asset ref for %s\n",pFileName));
//p_asset->SetPermanent(m_default_permanent); // <<<< this would also set the perm flag on the parent
p_asset->m_permanent = m_default_permanent; // just in the reference!!!
return true;
}
else
{
//Dbg_MsgAssert( 0, ( "This file was already loaded %s", pFileName ) );
return false;
}
}
else
{
if (!LoadOrGetAsset(pFileName, async_load, use_pip, m_default_permanent, 0))
{
Dbg_MsgAssert(0,("Failed to load anim %s",pFileName));
return false;
}
// Now add the reference to it, if one was requested
// this gets combined with the "reference checksum"
if (animName && !AssetAllocated(animName + referenceChecksum))
{
AddRef(pFileName, animName + referenceChecksum, referenceChecksum);
}
return true;
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::SetReferenceChecksum(uint32 reference_checksum)
{
// kind of a kludge for anims
m_reference_checksum = reference_checksum;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
uint32 CAssMan::GetReferenceChecksum() const
{
return m_reference_checksum;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
} // namespace Ass
#if 0
/******************************************************************/
/* */
/* */
/******************************************************************/
void CAssMan::DumpAssets()
{
CAsset * p_asset = mp_assetlist_head->mp_next;
int i=0;
while (p_asset != mp_assetlist_head)
{
CAsset *p_next = p_asset->mp_next;
printf ("Asset %3d: perm=%d %s\n",i,p_asset->m_permanent, p_asset->GetText());
i++;
p_asset = p_next;
}
}
#endif

124
Code/Gel/AssMan/AssMan.h Normal file
View File

@ -0,0 +1,124 @@
//****************************************************************************
//* MODULE: Gel/AssMan
//* FILENAME: AssMan.h
//* OWNER: Gary Jesdanun
//* CREATION DATE: 11/17/2000
//****************************************************************************
#ifndef __GEL_ASSMAN_H
#define __GEL_ASSMAN_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <core/hashtable.h>
#include <gel/assman/assettypes.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
namespace Lst
{
template<class _V> class HashTable;
}
namespace Script
{
class CStruct;
}
namespace Ass
{
class CAsset;
/*****************************************************************************
** Type Defines **
*****************************************************************************/
class CAssMan : public Spt::Class
{
DeclareSingletonClass( CAssMan );
public:
CAssMan( void );
~CAssMan( void );
// New generic functions
EAssetType FindAssetType(const char *p_assetName);
void* LoadAssetFromStream(uint32 asset_name, uint32 asset_type, uint32* p_data, int data_size, bool permanent, uint32 group);
void* LoadAsset(const char *p_assetName, bool async_load, bool use_pip = false, bool permanent = false, uint32 group = 0, void* pExtraData = NULL, Script::CStruct * pParams = NULL);
bool ReloadAsset( uint32 assetID, const char* pFileName, bool assertOnFail );
void* GetAsset(const char *p_assetName, bool assertOnFail = true);
void* GetAsset(uint32 assetID, bool assertOnFail = true);
void* LoadOrGetAsset(const char *p_assetName, bool async_load, bool use_pip, bool permanent = false, uint32 group = 0, void* pExtraData = NULL, Script::CStruct *pParams = NULL);
bool AssetAllocated(uint32 assetID);
bool AssetAllocated(const char *p_assetName);
bool AssetLoaded(uint32 assetID);
bool AssetLoaded(const char *p_assetName);
void AddRef(uint32 asset_id, uint32 ref_id, uint32 group = 0);
void AddRef(const char *p_assetName, uint32 ref_id, uint32 group = 0);
void SetReferenceChecksum(uint32 reference_checksum);
uint32 GetReferenceChecksum() const;
void SetDefaultPermanent(bool permanent);
bool GetDefaultPermanent() const;
void* GetFirstInGroup(uint32 group);
void* GetNthInGroup(uint32 group, int n);
int GetIndexInGroup(uint32 checksum);
int GetGroup(uint32 checksum);
int CountGroup(uint32 group);
int CountSameGroup(uint32 checksum);
void UnloadAllTables( bool destroy_permanent = false );
void DestroyReferences( CAsset* pAsset );
void UnloadAsset( CAsset* pAsset );
CAsset* GetAssetNode( uint32 assetID, bool assertOnFail );
// ideally, the LoadAnim function should be made more generic
bool LoadAnim(const char* pFileName, uint32 animName, uint32 referenceChecksum, bool async_load, bool use_pip);
private:
bool m_default_permanent;
uint32 m_reference_checksum; // used for anims, bit of a patch
Lst::HashTable<Ass::CAsset>* mp_asset_table;
CAsset* mp_assetlist_head;
};
/*****************************************************************************
** Private Declarations **
*****************************************************************************/
/*****************************************************************************
** Private Prototypes **
*****************************************************************************/
/*****************************************************************************
** Public Declarations **
*****************************************************************************/
/*****************************************************************************
** Public Prototypes **
*****************************************************************************/
/*****************************************************************************
** Inline Functions **
*****************************************************************************/
} // namespace Ass
#endif // __GEL_ASSMAN_H

View File

@ -0,0 +1,111 @@
///////////////////////////////////////////////////////////////////////////
// NodeArrayAsset.cpp
//
// Asset depended code for loading, unloading and reloading a node array
//
// Dave
//
#include <gel/assman/nodearrayasset.h>
#include <gel/assman/assettypes.h>
#include <gfx/nx.h>
#include <gel/scripting/symboltable.h>
#include <gel/scripting/script.h>
#include <sk/scripting/gs_file.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
int CNodeArrayAsset::Load( const char* p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pStruct)
{
SkateScript::LoadQB( p_file, Script::ASSERT_IF_DUPLICATE_SYMBOLS);
m_qb_checksum = Script::GenerateCRC( p_file );
char nodearrayname[128];
// Skip back to the backslash.
const char *p = &p_file[strlen( p_file ) - 1];
while( *p != '\\' && *p != '/') p--;
p++;
strcpy( nodearrayname, p ); // nodearrayname is now "name.qb"
sprintf( &nodearrayname[strlen( nodearrayname ) - 3], "_nodearray" ); // nodearrayname is now "name_nodearray"
void *p_data = Script::GetArray( nodearrayname );
// Set the array as the data returned when queried,
SetData( p_data );
Dbg_MsgAssert( p_data, ( "Could not find nodearray %s in %s", nodearrayname, p_file ));
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CNodeArrayAsset::Unload()
{
// Unload the asset.
SkateScript::UnloadQB( m_qb_checksum );
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CNodeArrayAsset::Reload( const char* p_file )
{
Dbg_Message( "Reloading %s", p_file );
Unload();
return( Load( p_file, false, 0, NULL, NULL ) == 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CNodeArrayAsset::LoadFinished()
{
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
const char* CNodeArrayAsset::Name()
{
// Printable name, for debugging.
return "Node Array";
}
/******************************************************************/
/* */
/* */
/******************************************************************/
EAssetType CNodeArrayAsset::GetType()
{
// type is hard wired into asset class
return ASSET_NODEARRAY;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
}

View File

@ -0,0 +1,36 @@
////////////////////////////////////////////////////////////////////////////
// animasset.h - interface between asset manager, and the actual animation
// provides a common interface to the
#ifndef __GEL_NODEARRAYASSET_H__
#define __GEL_NODEARRAYASSET_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <gel/assman/asset.h>
namespace Ass
{
class CNodeArrayAsset : public CAsset
{
public:
virtual int Load( const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct ); // create or load the asset
virtual int Unload(); // Unload the asset
virtual int Reload( const char *p_file);
virtual bool LoadFinished(); // Check to make sure asset is actually there
virtual const char * Name(); // printable name, for debugging
virtual EAssetType GetType(); // type is hard wired into asset class
private:
uint32 m_qb_checksum;
};
} // end namespace Ass
#endif // #ifndef __GEL_ASSET_H__

View File

@ -0,0 +1,168 @@
///////////////////////////////////////////////////////////////////////////
// AnimAsset.cpp
//
// Asset depended code for loading, unloading and reloading an animation
//
// Mick
//
#include <gel/assman/animasset.h>
#include <gel/assman/assettypes.h>
#include <gfx/bonedanim.h>
#include <gfx/nx.h>
#include <gel/scripting/symboltable.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAnimAsset::Load(const char* p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct) // create or load the asset
{
int errorCode = -1;
Mem::PushMemProfile((char*)p_file);
Gfx::CBonedAnimFrameData* pSeq = new Gfx::CBonedAnimFrameData;
char fullName[256];
// add extension to create name of platform-specific SKA file
sprintf( fullName, "%s.%s", p_file, Nx::CEngine::sGetPlatformExtension() );
// Load the data
if ( !pSeq->Load(fullName, true, async_load, use_pip) )
{
if ( Script::GetInteger( CRCD(0x25dc7904,"AssertOnMissingAssets") ) )
{
Dbg_MsgAssert( 0,( "Anim %s doesn't exist.", fullName ) );
}
delete pSeq;
pSeq = NULL;
goto failure;
}
// if we get this far, then it's successful
errorCode = 0;
failure:
// Add it to the list:
SetData( (void*)pSeq );
Mem::PopMemProfile(/*(char*)p_file*/);
return errorCode;
}
int CAnimAsset::Load(uint32* p_data, int data_size) // create or load the asset
{
int errorCode = -1;
char pDebugAssetString[256];
sprintf( pDebugAssetString, "anim from data stream" );
Mem::PushMemProfile((char*)pDebugAssetString);
Gfx::CBonedAnimFrameData* pSeq = new Gfx::CBonedAnimFrameData;
// Load the data
if ( !pSeq->Load(p_data, data_size, true ) )
{
if ( Script::GetInteger( CRCD(0x25dc7904,"AssertOnMissingAssets") ) )
{
Dbg_Assert( 0 );
}
delete pSeq;
pSeq = NULL;
goto failure;
}
// if we get this far, then it's successful
errorCode = 0;
failure:
// Add it to the list:
SetData( (void*)pSeq );
Mem::PopMemProfile(/*(char*)p_file*/);
return errorCode;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAnimAsset::Unload()
{
// Unload the asset
if (GetData())
{
delete (Gfx::CBonedAnimFrameData*) GetData();
SetData(NULL);
}
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CAnimAsset::Reload(const char* p_file)
{
Dbg_Message( "Reloading %s", p_file );
Unload();
return ( Load(p_file, false, 0, NULL, NULL ) == 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CAnimAsset::LoadFinished()
{
Gfx::CBonedAnimFrameData * p_anim = (Gfx::CBonedAnimFrameData*) GetData();
Dbg_MsgAssert(p_anim, ("LoadFinished(): Data pointer NULL (load probably was never started)"));
return p_anim->LoadFinished();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
const char* CAnimAsset::Name()
{
// printable name, for debugging
return "Animation";
}
/******************************************************************/
/* */
/* */
/******************************************************************/
EAssetType CAnimAsset::GetType()
{
// type is hard wired into asset class
return ASSET_ANIM;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
}

View File

@ -0,0 +1,40 @@
////////////////////////////////////////////////////////////////////////////
// animasset.h - interface between asset manager, and the actual animation
// provides a common interface to the
#ifndef __GEL_ANIMASSET_H__
#define __GEL_ANIMASSET_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <gel/assman/asset.h>
namespace Ass
{
class CAnimAsset : public CAsset
{
public:
virtual int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct); // create or load the asset
virtual int Load(uint32* p_data, int data_size); // create or load the asset
virtual int Unload(); // Unload the asset
virtual int Reload(const char *p_file);
virtual bool LoadFinished(); // Check to make sure asset is actually there
virtual const char * Name(); // printable name, for debugging
virtual EAssetType GetType(); // type is hard wired into asset class
private:
};
} // end namespace Ass
#endif // #ifndef __GEL_ASSET_H__

113
Code/Gel/AssMan/asset.cpp Normal file
View File

@ -0,0 +1,113 @@
///////////////////////////////////////////////////////////////////////////
// Asset.cpp
//
// Mick
//
// Base class of all assets
// provides basic interface to them
#include <gel/assman/asset.h>
#include <gel/assman/assettypes.h>
namespace Ass
{
// when destroying an asset, we also unload it
// this should only be done via the asset manager
CAsset::CAsset()
{
}
CAsset::~CAsset()
{
}
// Unlink for the doubly linked list
void CAsset::Unlink()
{
mp_next->mp_prev = mp_prev;
mp_prev->mp_next = mp_next;
mp_prev = this;
mp_next = this;
}
int CAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pParams)
{
Dbg_MsgAssert(0,("CAsset::Load() should not be called"));
return 0;
}
int CAsset::Load(uint32* p_data, int data_size)
{
Dbg_MsgAssert(0,("CAsset::Load() from data buffer should not be called"));
return 0;
}
int CAsset::Reload(const char *p_file)
{
Dbg_MsgAssert(0,("CAsset::Reload() should not be called"));
return 0;
}
int CAsset::Unload()
{
Dbg_MsgAssert(0,("CAsset::Unload() should not be called"));
return 0;
}
bool CAsset::LoadFinished()
{
Dbg_MsgAssert(0,("CAsset::LoadFinished() should not be called"));
return false;
}
const char * CAsset::Name() // printable name, for debugging
{
return "Unnamed Asset";
}
void * CAsset::GetData() // return a pointer to the asset's data
{
return mp_data;
}
void CAsset::SetData(void *p_data)
{
mp_data = p_data;
}
//----------------------------------------------------
void CAsset::SetID(uint32 id)
{
m_id = id;
}
uint32 CAsset::GetID()
{
return m_id;
}
void CAsset::SetGroup(uint32 group)
{
m_group = group;
}
uint32 CAsset::GetGroup()
{
return m_group;
}
EAssetType CAsset::GetType() // type is hard wired into asset class
{
return ASSET_UNKNOWN; // for now return 0, not sure if this should return the EAssetType
}
}

102
Code/Gel/AssMan/asset.h Normal file
View File

@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////
// asset.h - base class for managed assets
#ifndef __GEL_ASSET_H__
#define __GEL_ASSET_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <gel/assman/assettypes.h>
#include <core/string/cstring.h>
namespace Script
{
class CStruct;
}
namespace Ass
{
class CAsset : public Spt::Class
{
friend class CAssMan;
friend class CRefAsset;
protected:
CAsset(); // constructor is private, so only CAssMan can create them
virtual ~CAsset(); //
virtual int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pParams); // create or load the asset
virtual int Load(uint32* p_data, int data_size);
virtual int Unload(); // Unload the asset
virtual int Reload(const char *p_file);
virtual bool LoadFinished(); // Check to make sure asset is actually there
void Unlink(); // Unlink the asset
// Some acessor functions for memory usage metrics
virtual const char* Name(); // printable name, for debugging
// acessors for seting the low level id stuff
// maybe this should just be derived from CObject?
void SetID(uint32 id); // Unique asset ID
uint32 GetID();
virtual void SetGroup(uint32 group); // Unique group ID
virtual uint32 GetGroup();
virtual EAssetType GetType(); // type is hard wired into asset class
virtual void SetData(void *p_data); // return a pointer to the asset….
virtual void * GetData(); // return a pointer to the asset….
virtual void SetPermanent(bool perm);
void SetText(const char *p_text);
const char * GetText();
private:
uint32 m_id;
uint32 m_group;
char m_permanent; // should it stay in memory after a cleanup
char m_dead; // asset is dead, remove it
void * mp_data; // pointer to the asset data
// Str::String m_text;
protected:
CRefAsset * mp_ref_asset; // pointer to first CRefAsset that points to this
// The assets are also stored in a simple doubly linked list with a head node
// this is to simplify the
CAsset * mp_prev;
CAsset * mp_next;
};
//////////////////////////////////////////////////////////////////////////
// Inline member functions
inline void CAsset::SetText(const char *p_text)
{
// m_text = p_text;
}
inline const char * CAsset::GetText()
{
// return m_text.getString();
return "names removed";
}
inline void CAsset::SetPermanent(bool perm) {m_permanent = perm;}
} // end namespace Ass
#endif // #ifndef __GEL_ASSET_H__

View File

@ -0,0 +1,24 @@
// asset types for the asset manager
#ifndef __GEL_ASSETTYPES_H
#define __GEL_ASSETTYPES_H
namespace Ass
{
enum EAssetType {
ASSET_UNKNOWN, // unknown, needs to be determined by inspection
ASSET_BINARY, // binary file
ASSET_SCENE, // world_geometry
ASSET_TEXTURES, // Texture file
ASSET_COLLISION, // collision file
ASSET_ANIM, // animation
ASSET_SKELETON, // skeleton
ASSET_SKIN, // skin
ASSET_CUTSCENE, // cutscene
ASSET_NODEARRAY, // model node array
};
} // namespace Ass
#endif

View File

@ -0,0 +1,118 @@
//****************************************************************************
//* MODULE: Ass
//* FILENAME: cutsceneasset.cpp
//* OWNER: Gary Jesdanun
//* CREATION DATE: 01/13/2003
//****************************************************************************
#include <gel/assman/cutsceneasset.h>
#include <gel/assman/assettypes.h>
#include <gfx/nx.h>
#include <sk/objects/cutscenedetails.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
int CCutsceneAsset::Load( const char* p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct ) // create or load the asset
{
Mem::PushMemProfile( (char*)p_file );
Obj::CCutsceneData* p_cutsceneData = new Obj::CCutsceneData;
// get the platform-specific CUT file name
char platFileName[256];
sprintf( platFileName, "%s.%s", p_file, Nx::CEngine::sGetPlatformExtension() );
// load the data
if ( !p_cutsceneData->Load( platFileName, true, async_load ) )
{
Dbg_MsgAssert( 0, ( "Cutscene %s doesn't exist.", platFileName ) );
return -1;
}
// add it to the list:
SetData( (void*)p_cutsceneData );
Mem::PopMemProfile(/*(char*)p_file*/);
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CCutsceneAsset::Unload()
{
// Unload the asset
Obj::CCutsceneData* pData = (Obj::CCutsceneData*)GetData();
if ( pData )
{
delete pData;
SetData(NULL);
}
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CCutsceneAsset::Reload(const char* p_file)
{
Dbg_Message( "Reloading %s...", p_file );
Unload();
return ( Load( p_file, false, 0, NULL, NULL ) == 0 );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CCutsceneAsset::LoadFinished()
{
Obj::CCutsceneData* p_cutsceneData = (Obj::CCutsceneData*)GetData();
Dbg_MsgAssert( p_cutsceneData, ( "LoadFinished(): Data pointer NULL (load probably was never started)" ) );
return p_cutsceneData->LoadFinished();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
const char* CCutsceneAsset::Name()
{
// printable name, for debugging
return "Cutscene";
}
/******************************************************************/
/* */
/* */
/******************************************************************/
EAssetType CCutsceneAsset::GetType()
{
// type is hard wired into asset class
return ASSET_CUTSCENE;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
}

View File

@ -0,0 +1,46 @@
//****************************************************************************
//* MODULE: Ass
//* FILENAME: cutsceneasset.h
//* OWNER: Gary Jesdanun
//* CREATION DATE: 01/13/2003
//****************************************************************************
// interface between asset manager, and the actual cutscene
#ifndef __GEL_CUTSCENEASSET_H__
#define __GEL_CUTSCENEASSET_H__
#include <core/defines.h>
#include <core/support.h>
#include <gel/assman/asset.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
class CCutsceneAsset : public CAsset
{
public:
virtual int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct); // create or load the asset
virtual int Unload(); // unload the asset
virtual int Reload(const char *p_file);
virtual bool LoadFinished(); // check to make sure asset is actually there
virtual const char * Name(); // printable name, for debugging
virtual EAssetType GetType(); // type is hard wired into asset class
};
/******************************************************************/
/* */
/* */
/******************************************************************/
}
#endif

View File

@ -0,0 +1,156 @@
///////////////////////////////////////////////////////////////////////////
// RefAsset.cpp
//
// Mick
//
// Type of asset that just refers to another asset
// so you can have multiple indicies to reference an asset
#include <gel/assman/asset.h>
#include <gel/assman/refasset.h>
namespace Ass
{
CRefAsset::CRefAsset(CAsset *p_asset)
{
mp_asset = p_asset;
mp_sibling = NULL;
if (p_asset->mp_ref_asset == NULL)
{
// this is the first reference, so just stick it in mp_ref_asset
p_asset->mp_ref_asset = this;
}
else
{
// it's a new asset, so insert it as the head
// of siblings that refer to this
CRefAsset *p_other_ref = p_asset->mp_ref_asset;
p_asset->mp_ref_asset = this;
mp_sibling = p_other_ref;
}
mp_data = NULL; // Ref Assets explicitly have no data
m_permanent = p_asset->m_permanent; // inherit the permanence flag
}
CRefAsset::~CRefAsset()
{
// unhook the references
// from the assman table, the asset it refers to, and other assets
if (mp_asset)
{
CRefAsset * p_prev = mp_asset->mp_ref_asset;
if (p_prev == this)
{
mp_asset->mp_ref_asset = mp_sibling;
}
else
{
while (p_prev && p_prev->mp_sibling != this)
{
p_prev = p_prev->mp_sibling;
}
Dbg_MsgAssert(p_prev,("Reference not listed in its parent asset"));
p_prev->mp_sibling = mp_sibling;
}
mp_asset = NULL;
mp_sibling = NULL;
}
Dbg_MsgAssert(mp_asset == NULL,("Destroying ref with non-null asset"));
Dbg_MsgAssert(mp_sibling == NULL,("Destroying ref with non-null sibling"));
Dbg_MsgAssert(mp_data == NULL,("Ref Asset has data!"));
}
////////////////////////////////////////////////////////////////////////////////////
// all other functions simply call the appropiate function on the referenced asset
// (might want to make these inline later)
int CRefAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData) // create or load the asset
{
Dbg_MsgAssert(!async_load, ("Async load not supported on CRefAsset"));
// return mp_asset->Load(p_file);
return 0;
}
int CRefAsset::Unload() // Unload the asset
{
// return mp_asset->Unload();
return 0;
}
int CRefAsset::Reload(const char *p_file)
{
// printf("Reloading dereferenced asset with %s\n", p_file);
return mp_asset->Reload(p_file);
}
bool CRefAsset::LoadFinished()
{
Dbg_MsgAssert(GetData(), ("LoadFinished(): Data pointer NULL (load probably was never started)"));
return mp_asset->LoadFinished();
}
const char* CRefAsset::Name() // printable name, for debugging
{
return mp_asset->Name();
}
void CRefAsset::SetGroup(uint32 group) // Unique group ID
{
// mp_asset->SetGroup(group);
m_group = group;
}
uint32 CRefAsset::GetGroup()
{
// return mp_asset->GetGroup();
return m_group;
}
EAssetType CRefAsset::GetType() // type is hard wired into asset class
{
return mp_asset->GetType();
}
void CRefAsset::SetData(void *p_data) // return a pointer to the asset….
{
mp_asset->SetData(p_data);
}
void * CRefAsset::GetData() // return a pointer to the asset….
{
return mp_asset->GetData();
}
void CRefAsset::SetPermanent(bool perm)
{
m_permanent = perm;
mp_asset->SetPermanent(perm);
}
}

View File

@ -0,0 +1,53 @@
///////////////////////////////////////////////////////////
// asset.h - base class for managed assets
#ifndef __GEL_REFASSET_H__
#define __GEL_REFASSET_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <gel/assman/assettypes.h>
namespace Ass
{
class CRefAsset : public CAsset
{
friend class CAssMan;
protected:
CRefAsset(CAsset *p_asset);
~CRefAsset();
int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData); // create or load the asset
int Unload(); // Unload the asset
int Reload(const char *p_file);
bool LoadFinished(); // Check to make sure asset is actually there
int RamUsage();
int VramUsage();
int SramUsage();
const char* Name(); // printable name, for debugging
void SetGroup(uint32 group); // Unique group ID
uint32 GetGroup();
EAssetType GetType(); // type is hard wired into asset class
void SetData(void *p_data); // return a pointer to the asset….
void * GetData(); // return a pointer to the asset….
void SetPermanent(bool perm);
private:
CAsset * mp_asset; // pointer to the actual asset
CRefAsset * mp_sibling; // pointer to other CRefAsset that references mp_asset
};
//////////////////////////////////////////////////////////////////////////
// Inline member functions
} // end namespace Ass
#endif // #ifndef __GEL_REFASSET_H__

View File

@ -0,0 +1,137 @@
//****************************************************************************
//* MODULE: Ass
//* FILENAME: skeletonasset.cpp
//* OWNER: Gary Jesdanun
//* CREATION DATE: ??/??/????
//****************************************************************************
#include <gel/assman/skeletonasset.h>
#include <gel/assman/assettypes.h>
#include <gfx/nx.h>
#include <gfx/skeleton.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
int CSkeletonAsset::Load( const char *p_file, bool async_load, bool use_pip, void* pExtraData , Script::CStruct *pStruct) // create or load the asset
{
Dbg_MsgAssert( !async_load, ( "Async load not supported on CSkeletonAsset" ) );
// Load the data, add it to the list:
Gfx::CSkeletonData* pSkeletonData = new Gfx::CSkeletonData;
char fullName[256];
// add extension to create name of platform-specific SKE file
sprintf( fullName, "%s.%s", p_file, Nx::CEngine::sGetPlatformExtension() );
if ( !pSkeletonData->Load( fullName, true ) )
{
Dbg_MsgAssert( 0,( "File %s doesn't exist.", fullName ));
return -1;
}
SetData( (void*)pSkeletonData );
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CSkeletonAsset::Load( uint32* p_data, int data_size )
{
char pDebugAssetString[256];
sprintf( pDebugAssetString, "skeleton from data stream" );
Mem::PushMemProfile((char*)pDebugAssetString);
// Load the data, add it to the list:
Gfx::CSkeletonData* pSkeletonData = new Gfx::CSkeletonData;
if ( !pSkeletonData->Load( p_data, data_size, true ) )
{
Dbg_MsgAssert( 0,( "Couldn't create skeleton from data stream." ));
return -1;
}
SetData((void*)pSkeletonData);
Mem::PopMemProfile(/*"skeleton from data stream"*/);
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CSkeletonAsset::Unload() // Unload the asset
{
Gfx::CSkeletonData* pData = (Gfx::CSkeletonData*)GetData();
if ( pData )
{
delete pData;
SetData(NULL);
}
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CSkeletonAsset::Reload( const char *p_file )
{
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CSkeletonAsset::LoadFinished()
{
Dbg_MsgAssert( GetData(), ( "LoadFinished(): Data pointer NULL (load probably was never started)" ) );
// Since we don't support async, this is always true
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
const char * CSkeletonAsset::Name() // printable name, for debugging
{
return "Skeleton";
}
/******************************************************************/
/* */
/* */
/******************************************************************/
EAssetType CSkeletonAsset::GetType() // type is hard wired into asset class
{
return ASSET_SKELETON; // for now return 0, not sure if this should return the EAssetType
}
/******************************************************************/
/* */
/* */
/******************************************************************/
}

View File

@ -0,0 +1,47 @@
//****************************************************************************
//* MODULE: Ass
//* FILENAME: skeletonasset.h
//* OWNER: Gary Jesdanun
//* CREATION DATE: ??/??/????
//****************************************************************************
// interface between asset manager, and the actual skeleton data
// provides a common interface to the skeleton data
#ifndef __GEL_SKELETONASSET_H__
#define __GEL_SKELETONASSET_H__
#include <core/defines.h>
#include <core/support.h>
#include <gel/assman/asset.h>
namespace Ass
{
/******************************************************************/
/* */
/* */
/******************************************************************/
class CSkeletonAsset : public CAsset
{
public:
virtual int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct); // create or load the asset
virtual int Load(uint32* p_data, int data_size); // create or load the asset from data stream
virtual int Unload(); // unload the asset
virtual int Reload(const char *p_file);
virtual bool LoadFinished(); // check to make sure asset is actually there
virtual const char * Name(); // printable name, for debugging
virtual EAssetType GetType(); // type is hard wired into asset class
};
/******************************************************************/
/* */
/* */
/******************************************************************/
}
#endif

View File

@ -0,0 +1,161 @@
///////////////////////////////////////////////////////////////////////////
// SkinAsset.cpp
//
// Asset depended code for loading, unloading and reloading a skin
//
// Mick
//
#include <gel/assman/skinasset.h>
#include <core/string/stringutils.h>
#include <gel/assman/assettypes.h>
#include <gfx/nx.h>
#include <gfx/nxmesh.h>
namespace Ass
{
int CSkinAsset::Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct) // create or load the asset
{
Dbg_MsgAssert(!async_load, ("Async load not supported on CSkinAsset"));
Mem::PushMemProfile((char*)p_file);
SSkinAssetLoadContext theContext;
theContext.forceTexDictLookup = false;
theContext.doShadowVolume = false;
theContext.texDictOffset = 0;
// GJ: kludge to prevent tex dict offset clashes
// in bail board asset... i will remove this
// after i figure out why the tex dict offsets
// are clashing in the first place...
// if ( strstr(p_file,"board_default") )
// {
// texDictOffset = -1;
// }
if ( pExtraData )
{
theContext = *(SSkinAssetLoadContext*)pExtraData;
}
Nx::CMesh* pMesh = Nx::CEngine::sLoadMesh( p_file, theContext.texDictOffset, theContext.forceTexDictLookup, theContext.doShadowVolume );
if ( !pMesh )
{
Dbg_MsgAssert( 0,( "mesh %s doesn't exist.", p_file ));
return -1;
}
SetData((void*)pMesh);
// make sure the filename is in lower-case
char msg[128];
strcpy( msg, p_file );
Str::LowerCase( msg );
// only MDL files should load their collision data
if ( strstr( msg, ".mdl" ) )
{
// Might be overrided by having a "nocollision=1" as a parameter
int no_collision = 0;
if (pStruct)
{
pStruct->GetInteger(CRCD(0xbf29bc0,"nocollision"),&no_collision);
}
if (!no_collision)
{
pMesh->LoadCollision(p_file);
}
}
// Model node arrays are now loaded via the NodeArrayComponent.
// pMesh->LoadModelNodeArray(p_file);
Mem::PopMemProfile(/*"Skin"*/);
return 0;
}
int CSkinAsset::Load(uint32* p_data, int data_size) // create or load the asset
{
char pDebugAssetString[256];
sprintf( pDebugAssetString, "skin from data stream" );
Mem::PushMemProfile((char*)pDebugAssetString);
// GJ: for now, we need to access 3 pointers for the MDL, TEX, and CAS
// data... eventually, i'd like to store each of the 3 files
// separately in the asset manager, in which case we wouldn't
// have to do this clumsy hack of sending 3 pointers wrapped up
// in a struct...
SCutsceneModelDataInfo* p_cutscene_data = (SCutsceneModelDataInfo*)p_data;
Nx::CMesh* pMesh = Nx::CEngine::sLoadMesh( p_cutscene_data->modelChecksum,
p_cutscene_data->pModelData,
p_cutscene_data->modelDataSize,
p_cutscene_data->pCASData,
p_cutscene_data->texDictChecksum,
p_cutscene_data->pTextureData,
p_cutscene_data->textureDataSize,
p_cutscene_data->texDictOffset,
p_cutscene_data->isSkin,
p_cutscene_data->doShadowVolume );
if ( !pMesh )
{
Dbg_MsgAssert( 0,( "Couldn't create mesh from data stream." ));
return -1;
}
SetData((void*)pMesh);
// for now, we're going to assume that data loaded in through
// a data stream will not have collision or a node array,
// since we're only using this for cutscene assets right
// now... this can be changed very easily...
Mem::PopMemProfile(/*"skin from data stream"*/);
return 0;
}
int CSkinAsset::Unload() // Unload the asset
{
if (GetData())
{
Nx::CEngine::sUnloadMesh( (Nx::CMesh*) GetData() );
SetData(NULL);
}
return 0;
}
int CSkinAsset::Reload(const char *p_file)
{
return 0;
}
bool CSkinAsset::LoadFinished()
{
Dbg_MsgAssert(GetData(), ("LoadFinished(): Data pointer NULL (load probably was never started)"));
// Since we don't support async, this is always true
return true;
}
const char * CSkinAsset::Name() // printable name, for debugging
{
return "Skin";
}
EAssetType CSkinAsset::GetType() // type is hard wired into asset class
{
return ASSET_SKIN; // for now return 0, not sure if this should return the EAssetType
}
}

View File

@ -0,0 +1,59 @@
////////////////////////////////////////////////////////////////////////////
// skinasset.h - interface between asset manager, and the actual skin
// provides a common interface to the asset manager
#ifndef __GEL_SKINASSET_H__
#define __GEL_SKINASSET_H__
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <gel/assman/asset.h>
namespace Ass
{
struct SCutsceneModelDataInfo
{
uint32 modelChecksum;
uint32* pModelData;
int modelDataSize;
uint32* pTextureData;
int textureDataSize;
uint8* pCASData;
uint32 texDictChecksum;
int texDictOffset;
bool isSkin;
bool doShadowVolume;
};
struct SSkinAssetLoadContext
{
int forceTexDictLookup;
bool doShadowVolume;
int texDictOffset;
};
class CSkinAsset : public CAsset
{
public:
virtual int Load(const char *p_file, bool async_load, bool use_pip, void* pExtraData, Script::CStruct *pStruct); // create or load the asset
virtual int Load(uint32* p_data, int data_size); // create or load the asset
virtual int Unload(); // Unload the asset
virtual int Reload(const char *p_file);
virtual bool LoadFinished(); // Check to make sure asset is actually there
virtual const char * Name(); // printable name, for debugging
virtual EAssetType GetType(); // type is hard wired into asset class
private:
};
} // end namespace Ass
#endif // #ifndef __GEL_SKINASSET_H__

View File

@ -0,0 +1,482 @@
/*****************************************************************************
** **
** Neversoft Entertainment. **
** **
** Copyright (C) 1999 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: PS2 **
** **
** Module: Nx **
** **
** File name: gel\collision\BatchTriColl.cpp **
** **
** Created by: 04/12/02 - grj **
** **
** Description: **
** **
*****************************************************************************/
/*****************************************************************************
** Includes **
*****************************************************************************/
#include <core/defines.h>
#include <gel/collision/BatchTriColl.h>
#include <gel/collision/collision.h>
#ifdef __PLAT_NGPS__
#include <libdma.h>
#include <devvu0.h>
#include <gfx/ngps/nx/interrupts.h>
#include <gfx/ngps/nx/resource.h>
#endif //__PLAT_NGPS__
/*****************************************************************************
** DBG Information **
*****************************************************************************/
namespace Nx
{
#ifdef BATCH_TRI_COLLISION
CollData * CBatchTriColl::sp_coll_data;
volatile bool CBatchTriCollMan::s_processing = false;
volatile bool CBatchTriCollMan::s_result_processing = false;
volatile int CBatchTriCollMan::s_nested = 0;
volatile bool CBatchTriCollMan::s_found_collision = false;
CBatchTriColl CBatchTriCollMan::s_tri_collision_array[MAX_BATCH_COLLISIONS][2];
int CBatchTriCollMan::s_current_array = 0;
int CBatchTriCollMan::s_array_size = 0;
int CBatchTriCollMan::s_next_idx_to_batch = 0;
int CBatchTriCollMan::s_num_collisions = 0;
#ifdef __PLAT_NGPS__
int CBatchTriCollMan::s_collision_handler_id = -1;
bool CBatchTriCollMan::s_use_vu0_micro = false;
#endif
//----------------------------------------------------------------------------
//
#ifdef __PLAT_NGPS__
bool vu0RayTriangleCollision(const Mth::Vector *rayStart, const Mth::Vector *rayDir,
Mth::Vector *v0, Mth::Vector *v1, Mth::Vector *v2, float *t)
{
register bool result;
asm __volatile__(
"
.set noreorder
lqc2 vf06,0x0(%4) # v0
lqc2 vf08,0x0(%6) # v2
lqc2 vf07,0x0(%5) # v1
lqc2 vf04,0x0(%2) # rayStart
lqc2 vf05,0x0(%3) # rayDir
vcallms RayTriangleCollision # call microsubroutine
vnop # interlocking instruction, waits for vu0 completion
cfc2 %0,$vi02 # get boolean result from vu0
#li %0,1 # store 1 for return value
beq %0, $0, vu0RayTriDone # skip copy of t if not needed
nop
qmfc2 $8, $vf17 # move t to $8
sw $8, 0(%1) # and write out
vu0RayTriDone:
.set reorder
": "=r" (result), "+r" (t) : "r" (rayStart), "r" (rayDir), "r" (v0), "r" (v1) , "r" (v2) : "$8", "$9" );
return result;
}
#endif // __PLAT_NGPS__
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CBatchTriCollMan::sInit(CollData *p_coll_data)
{
// Check for nesting; abort if true
if (s_processing)
{
s_nested++;
return false;
}
Dbg_Assert(s_processing == false);
s_array_size = 0;
s_next_idx_to_batch = 0;
s_found_collision = false;
CBatchTriColl::sp_coll_data = p_coll_data;
#ifdef __PLAT_NGPS__
// install interrupt handler for render completion
if (s_collision_handler_id == -1)
{
s_collision_handler_id = AddIntcHandler(INTC_VU0, s_collision_done, 0);
EnableIntc(INTC_VU0);
sceDevVu0PutTBit(1); // Use T-bit interrupt
}
#endif // __PLAT_NGPS__
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CBatchTriCollMan::sFinish()
{
if (s_nested)
{
s_nested--;
Dbg_Assert(s_nested >= 0);
return;
}
// For now, don't wait for collision to finish, since we
// are trying to avoid a stall here. But this will probably
// cause deadlock situations once it is on the VU0.
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CBatchTriCollMan::sAddTriCollision(const Mth::Line &test_line, const Mth::Vector &test_line_dir,
CCollObj *p_collision_obj, FaceIndex face_index)
{
Dbg_Assert(s_nested == 0);
CBatchTriColl *p_tri_collision;
p_tri_collision = &(s_tri_collision_array[s_array_size++][s_current_array]);
p_tri_collision->m_test_line = test_line;
p_tri_collision->m_test_line_dir = test_line_dir;
p_tri_collision->mp_collision_obj = p_collision_obj;
p_tri_collision->m_face_index = face_index;
//Dbg_Assert(s_array_size <= MAX_BATCH_COLLISIONS);
if (s_array_size == MAX_BATCH_COLLISIONS)
{
// sWaitTriCollisions(); // make sure were done working
sStartNewTriCollisions();
//s_switch_buffers();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CBatchTriCollMan::sRemoveTriCollision(CBatchTriColl *p_tri_collision)
{
return false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CBatchTriCollMan::sStartNewTriCollisions()
{
Dbg_Assert(s_nested == 0);
sWaitTriCollisions(); // make sure were done working
Dbg_Assert(!s_processing);
// Check if we have anything to do
if (s_next_idx_to_batch >= s_array_size)
{
return;
}
s_processing = true;
#ifdef __PLAT_NGPS__
if(s_use_vu0_micro)
{
uint128 *p_vu0_mem = (uint128*)0x11004000; // VU0 data memory
// Write out sizes first
uint32 *p_vu0_word_mem = (uint32 *) (p_vu0_mem++);
*(p_vu0_word_mem++) = s_next_idx_to_batch;
*(p_vu0_word_mem++) = s_array_size;
for (int i = s_next_idx_to_batch; i < s_array_size; i++)
{
const CBatchTriColl &tri_coll = s_tri_collision_array[i][s_current_array];
Mth::Vector *v0, *v1, *v2;
if (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)
{
CCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
} else {
CCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
}
*(p_vu0_mem++) = *((uint128*) &(tri_coll.m_test_line.m_start));
*(p_vu0_mem++) = *((uint128*) &(tri_coll.m_test_line_dir));
*(p_vu0_mem++) = *((uint128*) v0);
*(p_vu0_mem++) = *((uint128*) v1);
*(p_vu0_mem++) = *((uint128*) v2);
}
//FlushCache(WRITEBACK_DCACHE);
//sceDevVu0PutTBit(1); // Use T-bit interrupt
// Switch the buffers before we make the call (in case it finishes immediately)
s_switch_buffers();
asm __volatile__(
"
.set noreorder
sync.l
vcallms BatchRayTriangleCollision # call microsubroutine
.set reorder
");
}
else
#endif // __PLAT_NGPS__
{
// Just do it manually now
for (int i = s_next_idx_to_batch; i < s_array_size; i++)
{
const CBatchTriColl &tri_coll = s_tri_collision_array[i][s_current_array];
Mth::Vector *v0, *v1, *v2;
if (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)
{
CCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
} else {
CCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
}
float distance;
#ifdef __PLAT_NGPS__
if (vu0RayTriangleCollision(&tri_coll.m_test_line.m_start, &tri_coll.m_test_line_dir, v0, v1, v2, &distance))
#else
if (CCollObj::sRayTriangleCollision(&tri_coll.m_test_line.m_start, &tri_coll.m_test_line_dir,
v0, v1, v2, &distance))
#endif
{
SCollSurface collisionSurface;
/* We've got one */
collisionSurface.point = (*v0);
collisionSurface.index = tri_coll.m_face_index;
// Find normal
Mth::Vector vTmp1(*v1 - *v0);
Mth::Vector vTmp2(*v2 - *v0);
collisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);
collisionSurface.normal.Normalize();
if (CCollObj::s_found_collision(&tri_coll.m_test_line, tri_coll.mp_collision_obj, &collisionSurface, distance, CBatchTriColl::sp_coll_data))
{
s_found_collision = true;
}
}
}
s_processing = false; // Just for manual version
s_switch_buffers();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
int CBatchTriCollMan::s_collision_done(int arg)
{
#ifdef __PLAT_NGPS__
// We should check to see if this is the T-bit first (instead of the debug D bit)
uint32 stat;
asm( "cfc2 %0, $vi29" :"=r"( stat ) : );
if ( !(stat & 0x4) )
{
ExitHandler();
return 0;
}
// Save floats
//unsigned int floatBuffer[32];
//saveFloatRegs(floatBuffer);
asm __volatile__(
"
.set noreorder
cfc2 %0,$vi01 # get number of collisions result from vu0
.set reorder
": "=r" (s_num_collisions) );
s_processing = false; // Tell that we are done
if (s_num_collisions > 0)
{
s_result_processing = true;
}
// restore floats
//restoreFloatRegs(floatBuffer);
ExitHandler();
#endif // __PLAT_NGPS__
return 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CBatchTriCollMan::s_process_results()
{
#ifdef __PLAT_NGPS__
SCollOutput *p_output = (SCollOutput*)0x11004010; // VU0 data memory
int previous_array = s_current_array ^ 1;
for (int i = 0; i < s_num_collisions; i++)
{
const CBatchTriColl &tri_coll = s_tri_collision_array[p_output->index][previous_array];
Mth::Vector *v0, *v1, *v2;
if (tri_coll.mp_collision_obj->mp_coll_tri_data->m_use_face_small)
{
CCollObjTriData::SFaceSmall *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_face_small[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
} else {
CCollObjTriData::SFace *face = &(tri_coll.mp_collision_obj->mp_coll_tri_data->mp_faces[tri_coll.m_face_index]);
v0 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[0]];
v1 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[1]];
v2 = &tri_coll.mp_collision_obj->mp_coll_tri_data->mp_vert_pos[face->m_vertex_index[2]];
}
SCollSurface collisionSurface;
/* We've got one */
collisionSurface.point = (*v0);
collisionSurface.index = tri_coll.m_face_index;
// Find normal
Mth::Vector vTmp1(*v1 - *v0);
Mth::Vector vTmp2(*v2 - *v0);
collisionSurface.normal = Mth::CrossProduct(vTmp1, vTmp2);
collisionSurface.normal.Normalize();
if (CCollObj::s_found_collision(&tri_coll.m_test_line, tri_coll.mp_collision_obj, &collisionSurface, p_output->distance, CBatchTriColl::sp_coll_data))
{
s_found_collision = true;
}
p_output++;
}
s_result_processing = false;
#else
Dbg_Assert(s_result_processing);
#endif // __PLAT_NGPS__
}
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CBatchTriCollMan::sWaitTriCollisions()
{
// Wait for collision to finish
while (s_processing)
;
if (s_result_processing)
{
s_process_results();
}
return s_found_collision;
}
#ifdef __PLAT_NGPS__
/******************************************************************/
/* */
/* */
/******************************************************************/
bool CBatchTriCollMan::sUseVU0Micro()
{
// Make sure we're not in the middle of something
Dbg_Assert(!s_processing);
Dbg_Assert(!s_result_processing);
return s_use_vu0_micro = NxPs2::CSystemResources::sRequestResource(NxPs2::CSystemResources::vVU0_MEMORY);
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CBatchTriCollMan::sDisableVU0Micro()
{
// Make sure we're not in the middle of something
Dbg_Assert(!s_processing);
Dbg_Assert(!s_result_processing);
if (s_use_vu0_micro)
{
NxPs2::CSystemResources::sFreeResource(NxPs2::CSystemResources::vVU0_MEMORY);
s_use_vu0_micro = false;
}
}
#endif // __PLAT_NGPS__
#endif // BATCH_TRI_COLLISION
} // namespace Nx

View File

@ -0,0 +1,163 @@
/*****************************************************************************
** **
** Neversoft Entertainment **
** **
** Copyright (C) 2002 - All Rights Reserved **
** **
******************************************************************************
** **
** Project: PS2 **
** **
** Module: Nx **
** **
** File name: BatchTriColl.h **
** **
** Created: 04/12/2002 - grj **
** **
*****************************************************************************/
#ifndef __GEL_BATCHTRICOLL_H
#define __GEL_BATCHTRICOLL_H
/*****************************************************************************
** Includes **
*****************************************************************************/
#ifndef __CORE_DEFINES_H
#include <core/defines.h>
#endif
#include <core/math.h>
#include <core/math/geometry.h>
#include <gel/collision/collenums.h>
/*****************************************************************************
** Defines **
*****************************************************************************/
#ifdef __PLAT_NGPS__
//#define BATCH_TRI_COLLISION
#endif
namespace Nx
{
#ifdef BATCH_TRI_COLLISION
class CCollObj;
class CollData;
/*****************************************************************************
** Class Definitions **
*****************************************************************************/
class CBatchTriColl
{
public:
Mth::Line m_test_line;
Mth::Vector m_test_line_dir;
CCollObj * mp_collision_obj;
float m_distance;
FaceIndex m_face_index;
static CollData * sp_coll_data; // We should only have one at a time
};
// Results from collision
struct SCollOutput
{
float distance;
int pad1;
int pad2;
int index;
};
class CBatchTriCollMan
{
public:
static bool sInit(CollData *p_coll_data);
static void sFinish();
static void sAddTriCollision(const Mth::Line &test_line, const Mth::Vector &test_line_dir,
CCollObj *p_collision_obj, FaceIndex face_index);
static bool sRemoveTriCollision(CBatchTriColl *p_tri_collsion);
static void sStartNewTriCollisions();
static volatile bool sIsTriCollisionDone();
static volatile bool sIsNested();
static bool sWaitTriCollisions();
#ifdef __PLAT_NGPS__
static bool sUseVU0Micro();
static void sDisableVU0Micro();
#endif
protected:
enum
{
MAX_BATCH_COLLISIONS = 40,
};
// Collision callback
static int s_collision_done(int);
static void s_process_results();
static void s_switch_buffers();
static volatile bool s_processing;
static volatile bool s_result_processing;
static volatile int s_nested; // Indicates nesting level, so normal collision must be used
static volatile bool s_found_collision;
static CBatchTriColl s_tri_collision_array[MAX_BATCH_COLLISIONS][2]; // Double buffered
static int s_current_array;
static int s_array_size;
static int s_next_idx_to_batch;
static int s_num_collisions;
static SCollOutput s_collision_results[MAX_BATCH_COLLISIONS];
private:
#ifdef __PLAT_NGPS__
static int s_collision_handler_id;// for interrupt callback
static bool s_use_vu0_micro;
#endif
};
/******************************************************************/
/* */
/* */
/******************************************************************/
inline volatile bool CBatchTriCollMan::sIsTriCollisionDone()
{
return !s_processing;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline volatile bool CBatchTriCollMan::sIsNested()
{
return s_nested > 0;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
inline void CBatchTriCollMan::s_switch_buffers()
{
s_array_size = 0;
s_next_idx_to_batch = 0;
s_current_array = s_current_array ^ 1;
}
#endif // BATCH_TRI_COLLISION
} // namespace Nx
#endif // __GEL_BATCHTRICOLL_H

Some files were not shown because too many files have changed in this diff Show More